Exemple #1
0
class TestResource(TestCase):
  """
  Test /search REST API
  """

  def setUp(self):
    super(TestResource, self).setUp()
    self.api = Api()
    self.object_generator = ObjectGenerator()
    self.create_objects()

  def create_objects(self):
    """Create objects to be searched.

    Creates five Requirements and makes relationships.
    0   1   2   3   4
    |---|   |---|   |
    |-------|-------|
    """
    self.objects = [
        self.object_generator.generate_object(all_models.Requirement)[1].id
        for _ in xrange(5)
    ]
    self.objects = all_models.Requirement.eager_query().filter(
        all_models.Requirement.id.in_(self.objects)
    ).all()
    for src, dst in [(0, 1), (0, 2), (2, 3), (2, 4)]:
      self.object_generator.generate_relationship(
          self.objects[src], self.objects[dst]
      )

  def search(self, *args, **kwargs):
    res, _ = self.api.search(*args, **kwargs)
    return res.json["results"]["entries"]

  def test_search_all(self):
    """Test search for all objects of a type."""
    res, _ = self.api.search("Requirement")
    self.assertEqual(len(res.json["results"]["entries"]), 5)

  def test_search_query(self):
    """Test search with query by title."""
    entries = self.search("Requirement", query=self.objects[0].title)
    self.assertEqual({entry["id"] for entry in entries},
                     {self.objects[0].id})

  def test_search_relevant(self):
    """Test search with 'relevant to' single object."""
    relevant_objects = "Requirement:{}".format(self.objects[0].id)
    entries = self.search("Requirement", relevant_objects=relevant_objects)
    self.assertEqual({entry["id"] for entry in entries},
                     {self.objects[i].id for i in [1, 2]})

  def test_search_relevant_multi(self):
    """Test search with 'relevant to' multiple objects."""
    ids = ",".join("Requirement:{}".format(self.objects[i].id) for i in (0, 3))
    entries = self.search("Requirement", relevant_objects=ids)
    self.assertEqual({entry["id"] for entry in entries},
                     {self.objects[2].id})
Exemple #2
0
class TestResource(TestCase):
    """
  Test /search REST API
  """
    def setUp(self):
        super(TestResource, self).setUp()
        self.api = Api()
        self.object_generator = ObjectGenerator()
        self.create_objects()

    def create_objects(self):
        """Create objects to be searched.

    Creates five Requirements and makes relationships.
    0   1   2   3   4
    |---|   |---|   |
    |-------|-------|
    """
        self.objects = [
            self.object_generator.generate_object(all_models.Requirement)[1].id
            for _ in xrange(5)
        ]
        self.objects = all_models.Requirement.eager_query().filter(
            all_models.Requirement.id.in_(self.objects)).all()
        for src, dst in [(0, 1), (0, 2), (2, 3), (2, 4)]:
            self.object_generator.generate_relationship(
                self.objects[src], self.objects[dst])

    def search(self, *args, **kwargs):
        res, _ = self.api.search(*args, **kwargs)
        return res.json["results"]["entries"]

    def test_search_all(self):
        """Test search for all objects of a type."""
        res, _ = self.api.search("Requirement")
        self.assertEqual(len(res.json["results"]["entries"]), 5)

    def test_search_query(self):
        """Test search with query by title."""
        entries = self.search("Requirement", query=self.objects[0].title)
        self.assertEqual({entry["id"]
                          for entry in entries}, {self.objects[0].id})

    def test_search_relevant(self):
        """Test search with 'relevant to' single object."""
        relevant_objects = "Requirement:{}".format(self.objects[0].id)
        entries = self.search("Requirement", relevant_objects=relevant_objects)
        self.assertEqual({entry["id"]
                          for entry in entries},
                         {self.objects[i].id
                          for i in [1, 2]})

    def test_search_relevant_multi(self):
        """Test search with 'relevant to' multiple objects."""
        ids = ",".join("Requirement:{}".format(self.objects[i].id)
                       for i in (0, 3))
        entries = self.search("Requirement", relevant_objects=ids)
        self.assertEqual({entry["id"]
                          for entry in entries}, {self.objects[2].id})
class TestRelationship(TestCase):
    """Integration test suite for Relationship."""

    # pylint: disable=invalid-name

    def setUp(self):
        """Create a Person, an Assessment, prepare a Relationship json."""
        super(TestRelationship, self).setUp()
        self.api = api_helper.Api()
        self.client.get("/login")
        self.object_generator = ObjectGenerator()
        self.person = factories.PersonFactory()
        self.assessment = factories.AssessmentFactory()

    HEADERS = {
        "Content-Type": "application/json",
        "X-requested-by": "GGRC",
    }
    REL_URL = "/api/relationships"

    @staticmethod
    def build_relationship_json(source, destination, is_external=False):
        """Builds relationship create request json."""
        return json.dumps([{
            "relationship": {
                "source": {
                    "id": source.id,
                    "type": source.type
                },
                "destination": {
                    "id": destination.id,
                    "type": destination.type
                },
                "context": {
                    "id": None
                },
                "is_external": is_external
            }
        }])

    def test_local_user_create_external_relationship(self):
        """Test that local user can't create external relationships"""
        with factories.single_commit():
            program = factories.ProgramFactory()
            comment = factories.CommentFactory()

        response = self.api.client.post(
            self.REL_URL,
            data=self.build_relationship_json(program,
                                              comment,
                                              is_external=True),
            headers=self.HEADERS)
        rel = all_models.Relationship.query.first()

        self.assert400(response)
        self.assertIsNone(rel)

    def test_changing_log_on_doc_change(self):
        """Changing object documents should generate new object revision."""
        url_link = u"www.foo.com"
        with factories.single_commit():
            control = factories.ControlFactory()
            url = factories.DocumentReferenceUrlFactory(link=url_link)

        def get_revisions():
            return all_models.Revision.query.filter(
                all_models.Revision.resource_id == control.id,
                all_models.Revision.resource_type == control.type,
            ).order_by(all_models.Revision.id.desc()).all()

        # attach an url to a control
        revisions = get_revisions()
        count = len(revisions)
        response = self.client.post(self.REL_URL,
                                    data=self.build_relationship_json(
                                        control, url),
                                    headers=self.HEADERS)
        self.assert200(response)

        relationship = all_models.Relationship.query.get(
            response.json[0][-1]["relationship"]["id"])

        # check if a revision was created and contains the attached url
        revisions = get_revisions()
        self.assertEqual(count + 1, len(revisions))
        url_list = revisions[0].content.get("documents_reference_url") or []
        self.assertEqual(1, len(url_list))
        self.assertIn("link", url_list[0])
        self.assertEqual(url_link, url_list[0]["link"])

        # now test whether a new revision is created when url is unmapped
        self.assert200(self.api.delete(relationship))

        revisions = get_revisions()
        self.assertEqual(count + 2, len(revisions))
        url_list = revisions[0].content.get("documents_reference_url") or []
        self.assertEqual(url_list, [])

    def test_relationship_disallowed_type(self):
        """Validation fails when source-destination are snapshottable."""
        audit = factories.AuditFactory()
        snapshottable = factories.ControlFactory()

        ctrl_revision = all_models.Revision.query.filter(
            all_models.Revision.resource_id == snapshottable.id,
            all_models.Revision.resource_type == snapshottable.type,
        ).first()
        snapshot = factories.SnapshotFactory(
            parent=audit,
            revision_id=ctrl_revision.id,
            child_type=snapshottable.type,
            child_id=snapshottable.id,
        )
        with self.assertRaises(ValidationError):
            factories.RelationshipFactory(source=snapshottable,
                                          destination=snapshot)
        with self.assertRaises(ValidationError):
            factories.RelationshipFactory(source=snapshot,
                                          destination=snapshottable)

    def test_relationship_validation(self):
        """Test validator that forbid creation of Relationship with the same object
    as source and destination"""
        response = self.client.post(self.REL_URL,
                                    data=self.build_relationship_json(
                                        self.assessment, self.assessment),
                                    headers=self.HEADERS)
        self.assert400(response)
        self.assertEqual(response.json[0][1],
                         "The mapping of object on itself is not possible")

    def test_reuse_relationship_on_post_swapped(self):
        """Test relationship is reused for 2nd POST with swapped src/dst"""
        with factories.single_commit():
            p1 = factories.ProgramFactory()
            p2 = factories.ProgramFactory()
            p1_id = p1.id
            p2_id = p2.id
            r1_id = factories.RelationshipFactory(source=p1, destination=p2).id

        resp, r2 = self.object_generator.generate_relationship(
            all_models.Program.query.get(p2_id),
            all_models.Program.query.get(p1_id))

        self.assert201(resp)
        self.assertEqual(r1_id, r2.id)

    def test_reuse_relationship_on_post_not_swapped(self):
        """Test relationship is reused for 2nd POST with not swapped src/dst"""
        with factories.single_commit():
            p1 = factories.ProgramFactory()
            p2 = factories.ProgramFactory()
            p1_id = p1.id
            p2_id = p2.id
            r1_id = factories.RelationshipFactory(source=p1, destination=p2).id

        resp, r2 = self.object_generator.generate_relationship(
            all_models.Program.query.get(p1_id),
            all_models.Program.query.get(p2_id))

        self.assert201(resp)
        self.assertEqual(r1_id, r2.id)
class TestExternalRelationship(TestCase):
    """Integration test suite for External Relationship."""

    # pylint: disable=invalid-name

    def setUp(self):
        """Init API helper"""
        super(TestExternalRelationship, self).setUp()
        self.object_generator = ObjectGenerator()
        self.api = api_helper.Api()
        with factories.single_commit():
            editor_role = all_models.Role.query.filter(
                all_models.Role.name == "Editor").first()
            self.person_ext = factories.PersonFactory(
                email="*****@*****.**")
            self.person_ext_id = self.person_ext.id
            self.person = factories.PersonFactory(
                email="*****@*****.**")
            self.person_id = self.person.id
            rbac_factories.UserRoleFactory(role=editor_role,
                                           person=self.person)

    HEADERS = {
        "Content-Type": "application/json",
        "X-requested-by": "External App",
        "X-ggrc-user": "******"email\": \"[email protected]\"}",
        "X-appengine-inbound-appid": "test_external_app",
    }
    REL_URL = "/api/relationships"

    @staticmethod
    def build_relationship_json(source, destination, is_external=True):
        """Builds relationship create request json."""
        return json.dumps([{
            "relationship": {
                "source": {
                    "id": source.id,
                    "type": source.type
                },
                "destination": {
                    "id": destination.id,
                    "type": destination.type
                },
                "context": {
                    "id": None
                },
                "is_external": is_external
            }
        }])

    @staticmethod
    def create_relationship(source, destination, is_external, user):
        """Creates relationship in database with given params."""
        return factories.RelationshipFactory(
            source=source,
            destination=destination,
            is_external=is_external,
            modified_by_id=user.id,
        )

    def test_create_ext_user_ext_relationship(self):
        """Validation external app user creates external relationship."""
        self.api.set_user(self.person_ext)
        with factories.single_commit():
            product = factories.ProductFactory()
            system = factories.SystemFactory()
        response = self.api.client.post(self.REL_URL,
                                        data=self.build_relationship_json(
                                            product, system, True),
                                        headers=self.HEADERS)
        self.assert200(response)

        relationship = all_models.Relationship.query.get(
            response.json[0][-1]["relationship"]["id"])
        self.assertEqual(relationship.source_type, "Product")
        self.assertEqual(relationship.source_id, product.id)
        self.assertEqual(relationship.destination_type, "System")
        self.assertEqual(relationship.destination_id, system.id)
        self.assertTrue(relationship.is_external)
        self.assertEqual(relationship.modified_by_id, self.person_ext.id)
        self.assertIsNone(relationship.parent_id)
        self.assertIsNone(relationship.automapping_id)
        self.assertIsNone(relationship.context_id)

    def test_create_ext_user_reg_relationship(self):
        """Validation external app user creates regular relationship."""
        self.api.set_user(self.person_ext)
        with factories.single_commit():
            product = factories.ProductFactory()
            system = factories.SystemFactory()
        response = self.api.client.post(self.REL_URL,
                                        data=self.build_relationship_json(
                                            product, system, False),
                                        headers=self.HEADERS)
        self.assert400(response)
        self.assertEqual(response.json[0], [
            400,
            "You do not have the necessary permissions to "
            "create regular relationships.",
        ])

    def test_update_ext_user_ext_relationship(self):
        """Validation external app user updates external relationship."""
        self.api.set_user(self.person_ext)
        with factories.single_commit():
            product = factories.ProductFactory()
            system = factories.SystemFactory()

        self.create_relationship(product, system, True, self.person_ext)
        response = self.api.client.post(self.REL_URL,
                                        data=self.build_relationship_json(
                                            product, system, True),
                                        headers=self.HEADERS)
        self.assert200(response)

        relationship = all_models.Relationship.query.get(
            response.json[0][-1]["relationship"]["id"])
        self.assertEqual(relationship.source_type, "Product")
        self.assertEqual(relationship.source_id, product.id)
        self.assertEqual(relationship.destination_type, "System")
        self.assertEqual(relationship.destination_id, system.id)
        self.assertTrue(relationship.is_external)
        self.assertEqual(relationship.modified_by_id, self.person_ext.id)
        self.assertIsNone(relationship.parent_id)
        self.assertIsNone(relationship.automapping_id)
        self.assertIsNone(relationship.context_id)

    def test_update_ext_user_reg_relationship(self):
        """External app user can update regular relationship."""
        with factories.single_commit():
            product = factories.ProductFactory()
            system = factories.SystemFactory()
            self.create_relationship(product, system, False, self.person)
            product_id = product.id
            system_id = system.id

        self.api.set_user(self.person_ext)
        product = all_models.Product.query.get(product_id)
        system = all_models.System.query.get(system_id)
        response = self.api.client.post(self.REL_URL,
                                        data=self.build_relationship_json(
                                            product, system, True),
                                        headers=self.HEADERS)
        self.assert200(response)
        self.assertEqual(response.json[0][1]["relationship"]["is_external"],
                         True)

    def test_delete_ext_user_ext_relationship(self):
        """Validation external app user deletes external relationship."""
        self.api.set_user(self.person_ext)
        with factories.single_commit():
            product = factories.ProductFactory()
            system = factories.SystemFactory()
            rel = self.create_relationship(product, system, True,
                                           self.person_ext)

        response = self.api.delete(rel)
        self.assert200(response)
        relationship = all_models.Relationship.query.get(rel.id)
        self.assertIsNone(relationship)

    def test_delete_ext_user_reg_relationship(self):
        """External app user can delete regular relationship."""
        self.api.set_user(self.person_ext)
        with factories.single_commit():
            product = factories.ProductFactory()
            system = factories.SystemFactory()

        rel = self.create_relationship(product, system, False, self.person_ext)
        response = self.api.delete(rel)
        self.assert200(response)

    def test_update_reg_user_ext_relationship(self):
        """Validation regular app user updates external relationship."""
        with factories.single_commit():
            product = factories.ProductFactory()
            system = factories.SystemFactory()
            self.create_relationship(product, system, True, self.person_ext)
            product_id = product.id
            system_id = system.id

        self.api.set_user(self.person)
        product = all_models.Product.query.get(product_id)
        system = all_models.System.query.get(system_id)
        response = self.api.client.post(self.REL_URL,
                                        data=self.build_relationship_json(
                                            product, system, False),
                                        headers=self.HEADERS)
        self.assert200(response)

    def test_delete_reg_user_ext_relationship(self):
        """Validation regular user deletes external relationship."""
        with factories.single_commit():
            product = factories.ProductFactory()
            system = factories.SystemFactory()
            self.create_relationship(product, system, True, self.person_ext)

        self.api.set_user(self.person)
        rel = all_models.Relationship.query.first()
        response = self.api.delete(rel)
        self.assert200(response)
        relationship = all_models.Relationship.query.get(rel.id)
        self.assertIsNone(relationship)

    @ddt.data(*READONLY_MAPPING_PAIRS)
    @ddt.unpack
    def test_local_delete_relationship_scoping_directive(self, model1, model2):
        """Test deletion of relationship between {0.__name__} and {1.__name__}"""

        # Set up relationships
        with self.object_generator.api.as_external():
            _, obj1 = self.object_generator.generate_object(model1)
            _, obj2 = self.object_generator.generate_object(model2)

            _, rel = self.object_generator.generate_relationship(
                obj1, obj2, is_external=True)

        # check that relationship cannot be deleted by regular user
        self.api.set_user(all_models.Person.query.get(self.person_id))
        relationship = all_models.Relationship.query.get(rel.id)
        response = self.api.delete(relationship)
        self.assert400(response)

    @ddt.data(*READONLY_MAPPING_PAIRS)
    @ddt.unpack
    def test_local_create_relationship_scoping_directive(self, model1, model2):
        """Test creation of relationship between {0.__name__} and {1.__name__}"""
        # Set up relationships
        with self.object_generator.api.as_external():
            _, obj1 = self.object_generator.generate_object(model1)
            _, obj2 = self.object_generator.generate_object(model2)

        self.object_generator.api.set_user(
            all_models.Person.query.get(self.person_id))

        response, _ = self.object_generator.generate_relationship(
            obj1, obj2, is_external=True)

        self.assert400(response)

    @ddt.data(*READONLY_MAPPING_PAIRS)
    @ddt.unpack
    def test_ext_create_delete_relationship_scoping_directive(
            self, model1, model2):
        """Test ext user and relationship between {0.__name__} and {1.__name__}"""

        # Set up relationships
        with self.object_generator.api.as_external():
            _, obj1 = self.object_generator.generate_object(model1)
            _, obj2 = self.object_generator.generate_object(model2)

            _, rel = self.object_generator.generate_relationship(
                obj1, obj2, is_external=True)

            self.assertIsNotNone(rel)

        # check that external relationship can be deleted by external user
        self.api.set_user(all_models.Person.query.get(self.person_ext_id))
        relationship = all_models.Relationship.query.get(rel.id)
        response = self.api.delete(relationship)
        print response.json
        self.assert200(response)
Exemple #5
0
class TestReader(TestCase):
  """ Test reader role """

  def setUp(self):
    super(TestReader, self).setUp()
    self.api = Api()
    self.object_generator = ObjectGenerator()
    self.init_users()

  def init_users(self):
    """ Init users needed by the test cases """
    users = [("reader", "Reader"),
             ("admin", "Administrator"),
             ("creator", "Creator")]
    self.users = {}
    for (name, role) in users:
      _, user = self.object_generator.generate_person(
          data={"name": name}, user_role=role)
      self.users[name] = user

    self.users["external"] = self.object_generator.generate_person(
        data={"email": "*****@*****.**"})[1]

  def test_admin_page_access(self):
    """Only admin can use admin requirement"""
    for role, code in (("reader", 403), ("admin", 200)):
      self.api.set_user(self.users[role])
      self.assertEqual(self.api.client.get("/admin").status_code, code)

  def test_reader_can_crud(self):
    """ Test Basic create/read,update/delete operations """
    self.api.set_user(self.users["reader"])
    all_errors = []
    base_models = set([
        "DataAsset", "Contract",
        "Policy", "Regulation", "Standard", "Document", "Facility",
        "Market", "Objective", "OrgGroup", "Vendor", "Product",
        "System", "Process", "Project", "AccessGroup",
        "Metric", "TechnologyEnvironment", "ProductGroup", "KeyReport",
        "AccountBalance",
    ])
    for model_singular in base_models:
      try:
        model = get_model(model_singular)
        table_singular = model._inflector.table_singular
        table_plural = model._inflector.table_plural
        # Test POST creation
        response, _ = self.object_generator.generate_object(
            model,
            data={
                table_singular: {
                    "title": model_singular,
                    "context": None,
                    "documents_reference_url": "ref",
                    "link": "https://example.com",  # only for Document
                    "contact": {
                        "type": "Person",
                        "id": self.users["reader"].id,
                    }
                },
            }
        )

        if response.status_code != 201:
          all_errors.append("{} post creation failed {} {}".format(
              model_singular, response.status, response.data))
          continue

        obj_id = response.json.get(table_singular).get("id")

        # Test GET when owner
        response = self.api.get(model, obj_id)
        if response.status_code != 200:
          all_errors.append("{} can't GET object {}".format(
              model_singular, response.status))
          continue

        # Test GET collection when owner
        response = self.api.get_collection(model, obj_id)
        collection = response.json.get(
            "{}_collection".format(table_plural)).get(table_plural)
        if not collection:
          all_errors.append(
              "{} cannot retrieve object even if owner (collection)".format(
                  model_singular))
          continue
      except:
        all_errors.append("{} exception thrown".format(model_singular))
        raise
    self.assertEqual(all_errors, [])

  def test_reader_search(self):
    """ Test if reader can see the correct object while using search api """
    self.api.set_user(self.users['admin'])
    self.api.post(all_models.Regulation, {
        "regulation": {"title": "Admin regulation", "context": None},
    })
    self.api.set_user(self.users['reader'])
    response = self.api.post(all_models.Policy, {
        "policy": {"title": "reader Policy", "context": None},
    })
    response, _ = self.api.search("Regulation,Policy")
    entries = response.json["results"]["entries"]
    self.assertEqual(len(entries), 2)
    response, _ = self.api.search("Regulation,Policy", counts=True)
    self.assertEqual(response.json["results"]["counts"]["Policy"], 1)
    self.assertEqual(response.json["results"]["counts"]["Regulation"], 1)

  def _get_count(self, obj):
    """ Return the number of counts for the given object from search """
    response, _ = self.api.search(obj, counts=True)
    return response.json["results"]["counts"].get(obj)

  def test_reader_should_see_users(self):
    """ Test if creator can see all the users in the system """
    self.api.set_user(self.users['admin'])
    admin_count = self._get_count("Person")
    self.api.set_user(self.users['reader'])
    reader_count = self._get_count("Person")
    self.assertEqual(admin_count, reader_count)

  def test_relationships_access(self):
    """Check if reader can access relationship objects"""
    self.api.set_user(self.users['admin'])
    _, first_regulation = self.object_generator.generate_object(
        all_models.Regulation,
        data={"regulation": {"title": "Test regulation", "context": None}}
    )
    _, second_regulation = self.object_generator.generate_object(
        all_models.Regulation,
        data={"regulation": {"title": "Test regulation 2", "context": None}}
    )
    response, rel = self.object_generator.generate_relationship(
        first_regulation, second_regulation
    )
    self.assertStatus(response, 201)
    self.api.set_user(self.users['reader'])
    response = self.api.get_collection(all_models.Relationship, rel.id)
    self.assert200(response)
    num = len(response.json["relationships_collection"]["relationships"])
    self.assertEqual(num, 1)

  def test_creation_of_mappings(self):
    """Check if reader can't create mappings"""
    self.object_generator.api.set_user(self.users["external"])
    _, control = self.object_generator.generate_object(
        all_models.Control,
        data={"control": {"title": "Test Control", "context": None}}
    )

    self.object_generator.api.set_user(self.users['reader'])
    _, program = self.object_generator.generate_object(
        all_models.Program,
        data={"program": {"title": "Test Program", "context": None}}
    )

    response, _ = self.object_generator.generate_relationship(
        control, program, program.context
    )
    self.assert403(response)

  @ddt.data("creator", "reader")
  def test_unmap_people(self, user_role):
    """Test that global reader/creator can't unmap people from program"""
    user = self.users[user_role]
    with factories.single_commit():
      program = factories.ProgramFactory()
      mapped_person = factories.ObjectPersonFactory(
          personable=program, person=user, context=program.context
      )
    self.api.set_user(user)
    db.session.add(mapped_person)
    response = self.api.delete(mapped_person)
    self.assert403(response)

  def test_read_evidence_revision(self):
    """Global Read can read Evidence revision content"""
    user = self.users["reader"]
    link = "google.com"
    evidence = factories.EvidenceUrlFactory(link=link)
    evidence_id = evidence.id
    self.api.set_user(user)
    resp = self.api.client.get(
        "/api/revisions?resource_type={}&resource_id={}".format(evidence.type,
                                                                evidence_id))
    rev_content = resp.json["revisions_collection"]["revisions"][0]["content"]
    self.assertTrue(rev_content)
    self.assertEquals(link, rev_content["link"])
Exemple #6
0
class TestReader(TestCase):
    """ Test reader role """
    def setUp(self):
        super(TestReader, self).setUp()
        self.api = Api()
        self.object_generator = ObjectGenerator()
        self.init_users()

    def init_users(self):
        """ Init users needed by the test cases """
        users = [("reader", "Reader"), ("admin", "Administrator"),
                 ("creator", "Creator")]
        self.users = {}
        for (name, role) in users:
            _, user = self.object_generator.generate_person(
                data={"name": name}, user_role=role)
            self.users[name] = user

    def test_admin_page_access(self):
        """Only admin can use admin requirement"""
        for role, code in (("reader", 403), ("admin", 200)):
            self.api.set_user(self.users[role])
            self.assertEqual(self.api.client.get("/admin").status_code, code)

    def test_reader_can_crud(self):
        """ Test Basic create/read,update/delete operations """
        self.api.set_user(self.users["reader"])
        all_errors = []
        base_models = set([
            "Control",
            "DataAsset",
            "Contract",
            "Policy",
            "Regulation",
            "Standard",
            "Document",
            "Facility",
            "Market",
            "Objective",
            "OrgGroup",
            "Vendor",
            "Product",
            "System",
            "Process",
            "Project",
            "AccessGroup",
            "Metric",
            "TechnologyEnvironment",
            "ProductGroup",
        ])
        for model_singular in base_models:
            try:
                model = get_model(model_singular)
                table_singular = model._inflector.table_singular
                table_plural = model._inflector.table_plural
                # Test POST creation
                response, _ = self.object_generator.generate_object(
                    model,
                    data={
                        table_singular: {
                            "title": model_singular,
                            "context": None,
                            "documents_reference_url": "ref",
                            "link": "https://example.com",  # only for Document
                            "contact": {
                                "type": "Person",
                                "id": self.users["reader"].id,
                            }
                        },
                    })

                if response.status_code != 201:
                    all_errors.append("{} post creation failed {} {}".format(
                        model_singular, response.status, response.data))
                    continue

                obj_id = response.json.get(table_singular).get("id")

                # Test GET when owner
                response = self.api.get(model, obj_id)
                if response.status_code != 200:
                    all_errors.append("{} can't GET object {}".format(
                        model_singular, response.status))
                    continue

                # Test GET collection when owner
                response = self.api.get_collection(model, obj_id)
                collection = response.json.get(
                    "{}_collection".format(table_plural)).get(table_plural)
                if not collection:
                    all_errors.append(
                        "{} cannot retrieve object even if owner (collection)".
                        format(model_singular))
                    continue
            except:
                all_errors.append("{} exception thrown".format(model_singular))
                raise
        self.assertEqual(all_errors, [])

    def test_reader_search(self):
        """ Test if reader can see the correct object while using search api """
        self.api.set_user(self.users['admin'])
        self.api.post(all_models.Regulation, {
            "regulation": {
                "title": "Admin regulation",
                "context": None
            },
        })
        self.api.set_user(self.users['reader'])
        response = self.api.post(all_models.Policy, {
            "policy": {
                "title": "reader Policy",
                "context": None
            },
        })
        response, _ = self.api.search("Regulation,Policy")
        entries = response.json["results"]["entries"]
        self.assertEqual(len(entries), 2)
        response, _ = self.api.search("Regulation,Policy", counts=True)
        self.assertEqual(response.json["results"]["counts"]["Policy"], 1)
        self.assertEqual(response.json["results"]["counts"]["Regulation"], 1)

    def _get_count(self, obj):
        """ Return the number of counts for the given object from search """
        response, _ = self.api.search(obj, counts=True)
        return response.json["results"]["counts"].get(obj)

    def test_reader_should_see_users(self):
        """ Test if creator can see all the users in the system """
        self.api.set_user(self.users['admin'])
        admin_count = self._get_count("Person")
        self.api.set_user(self.users['reader'])
        reader_count = self._get_count("Person")
        self.assertEqual(admin_count, reader_count)

    def test_relationships_access(self):
        """Check if reader can access relationship objects"""
        self.api.set_user(self.users['admin'])
        _, first_regulation = self.object_generator.generate_object(
            all_models.Regulation,
            data={"regulation": {
                "title": "Test regulation",
                "context": None
            }})
        _, second_regulation = self.object_generator.generate_object(
            all_models.Regulation,
            data={
                "regulation": {
                    "title": "Test regulation 2",
                    "context": None
                }
            })
        response, rel = self.object_generator.generate_relationship(
            first_regulation, second_regulation)
        self.assertStatus(response, 201)
        self.api.set_user(self.users['reader'])
        response = self.api.get_collection(all_models.Relationship, rel.id)
        self.assert200(response)
        num = len(response.json["relationships_collection"]["relationships"])
        self.assertEqual(num, 1)

    def test_creation_of_mappings(self):
        """Check if reader can't create mappings"""
        self.object_generator.api.set_user(self.users["admin"])
        _, control = self.object_generator.generate_object(
            all_models.Control,
            data={"control": {
                "title": "Test Control",
                "context": None
            }})

        self.object_generator.api.set_user(self.users['reader'])
        _, program = self.object_generator.generate_object(
            all_models.Program,
            data={"program": {
                "title": "Test Program",
                "context": None
            }})

        response, _ = self.object_generator.generate_relationship(
            control, program, program.context)
        self.assert403(response)

    @ddt.data("creator", "reader")
    def test_unmap_people(self, user_role):
        """Test that global reader/creator can't unmap people from program"""
        user = self.users[user_role]
        with factories.single_commit():
            program = factories.ProgramFactory()
            mapped_person = factories.ObjectPersonFactory(
                personable=program, person=user, context=program.context)
        self.api.set_user(user)
        db.session.add(mapped_person)
        response = self.api.delete(mapped_person)
        self.assert403(response)

    def test_read_evidence_revision(self):
        """Global Read can read Evidence revision content"""
        user = self.users["reader"]
        link = "google.com"
        evidence = factories.EvidenceUrlFactory(link=link)
        evidence_id = evidence.id
        self.api.set_user(user)
        resp = self.api.client.get(
            "/api/revisions?resource_type={}&resource_id={}".format(
                evidence.type, evidence_id))
        rev_content = resp.json["revisions_collection"]["revisions"][0][
            "content"]
        self.assertTrue(rev_content)
        self.assertEquals(link, rev_content["link"])
Exemple #7
0
class TestResource(TestCase):
    """
  Test /search REST API
  """
    def setUp(self):
        super(TestResource, self).setUp()
        self.api = Api()
        self.object_generator = ObjectGenerator()
        self.create_objects()

    def create_objects(self):
        """Create objects to be searched.

    Creates five controls and makes relationships.
    0   1   2   3   4
    |---|   |---|   |
    |-------|-------|
    """
        self.objects = [
            self.object_generator.generate_object(Control)[1].id
            for _ in xrange(5)
        ]
        self.objects = Control.eager_query().filter(
            Control.id.in_(self.objects)).all()
        for src, dst in [(0, 1), (0, 2), (2, 3), (2, 4)]:
            self.object_generator.generate_relationship(
                self.objects[src], self.objects[dst])

    def search(self, *args, **kwargs):
        res, _ = self.api.search(*args, **kwargs)
        return res.json["results"]["entries"]

    def test_search_all(self):
        """Test search for all objects of a type."""
        res, _ = self.api.search("Control")
        self.assertEqual(len(res.json["results"]["entries"]), 5)

    def test_search_query(self):
        """Test search with query by title."""
        entries = self.search("Control", query=self.objects[0].title)
        self.assertEqual({entry["id"]
                          for entry in entries}, {self.objects[0].id})

    def test_search_relevant(self):
        """Test search with 'relevant to' single object."""
        relevant_objects = "Control:{}".format(self.objects[0].id)
        entries = self.search("Control", relevant_objects=relevant_objects)
        self.assertEqual({entry["id"]
                          for entry in entries},
                         {self.objects[i].id
                          for i in [1, 2]})

    def test_search_relevant_multi(self):
        """Test search with 'relevant to' multiple objects."""
        ids = ",".join("Control:{}".format(self.objects[i].id) for i in (0, 3))
        entries = self.search("Control", relevant_objects=ids)
        self.assertEqual({entry["id"]
                          for entry in entries}, {self.objects[2].id})

    def test_search_fail_with_terms_none(self):
        """Test search to fail with BadRequest (400 Error) when terms are None."""
        query = '/search?types={}&counts_only={}'.format("Control", False)
        response = self.api.client.get(query)
        self.assert400(response)
        self.assertEqual(
            response.json['message'], 'Query parameter "q" '
            'specifying search terms must be provided.')
Exemple #8
0
class TestWithReadOnlyAccessAPI(TestCase, query_helper.WithQueryApi):
  """Test WithReadOnlyAccess mixin"""

  def setUp(self):
    super(TestWithReadOnlyAccessAPI, self).setUp()
    self.object_generator = ObjectGenerator()
    self.object_generator.api.login_as_normal()

  @ddt.data(
      ('System', True),
      ('System', False),
      ('System', None),
      ('System', _NOT_SPECIFIED),
      ('System', "qwert"),
  )
  @ddt.unpack
  def test_readonly_ignored_on_post(self, obj_type, readonly):
    """Test flag readonly ignored on object {0} POST for body readonly={1}"""

    dct = dict()
    if readonly is not _NOT_SPECIFIED:
      dct['readonly'] = readonly
    resp, obj = self.object_generator.generate_object(
        get_model(obj_type),
        dct,
    )

    self.assertStatus(resp, 201)
    self.assertFalse(obj.readonly)

  @ddt.data(
      ('System', True, True),
      ('System', False, False),
      ('System', None, False),
      ('System', _NOT_SPECIFIED, False),
  )
  @ddt.unpack
  def test_readonly_set_on_post_as_external(self, obj_type, readonly, result):
    """Test flag readonly on {0} POST for body readonly={1} as external user"""

    dct = dict()
    if readonly is not _NOT_SPECIFIED:
      dct['readonly'] = readonly

    with self.object_generator.api.as_external():
      resp, obj = self.object_generator.generate_object(
          get_model(obj_type),
          dct,
      )
      obj_id = obj.id

    self.assertStatus(resp, 201)
    obj = get_model(obj_type).query.get(obj_id)
    self.assertEqual(obj.readonly, result)

  @ddt.data(
      ('System', False, False, 200),
      ('System', False, True, 200),
      ('System', False, None, 200),
      ('System', False, _NOT_SPECIFIED, 200),
      ('System', False, "qwerty", 200),
      ('System', True, False, 405),
      ('System', True, True, 405),
      ('System', True, None, 405),
      ('System', True, _NOT_SPECIFIED, 405),
      ('System', True, "qwerty", 405),
  )
  @ddt.unpack
  def test_put(self, obj_type, current, new, exp_code):
    """Test {0} PUT readonly={2} for current readonly={1}"""

    factory = factories.get_model_factory(obj_type)
    with factories.single_commit():
      obj = factory(title='a', readonly=current)
      obj_id = obj.id

    data = {'title': 'b'}
    if new is not _NOT_SPECIFIED:
      data['readonly'] = new

    resp = self.object_generator.api.put(obj, data)

    self.assertStatus(resp, exp_code)
    obj = get_model(obj_type).query.get(obj_id)
    self.assertEqual(obj.readonly, current)

  @ddt.data(
      ('System', False, False, 200, False),
      ('System', False, True, 200, True),
      ('System', False, None, 200, False),
      ('System', False, _NOT_SPECIFIED, 200, False),
      ('System', True, False, 200, False),
      ('System', True, True, 200, True),
      ('System', True, None, 200, True),
      ('System', True, _NOT_SPECIFIED, 200, True),
  )
  @ddt.unpack
  def test_put_as_external(self, obj_type, current, new, exp_code,
                           exp_readonly):
    """Test {0} PUT readonly={2} for current readonly={1} for external user"""

    factory = factories.get_model_factory(obj_type)
    with factories.single_commit():
      obj = factory(title='a', readonly=current)
      obj_id = obj.id

    data = {'title': 'b'}
    if new is not _NOT_SPECIFIED:
      data['readonly'] = new

    with self.object_generator.api.as_external():
      obj = get_model(obj_type).query.get(obj_id)
      resp = self.object_generator.api.put(obj, data)

    self.assertStatus(resp, exp_code)
    obj = get_model(obj_type).query.get(obj_id)
    self.assertEqual(obj.readonly, exp_readonly)

  @ddt.data('System')
  def test_403_if_put_readonly_without_perms(self, obj_type):
    """Test {0} with readonly=True PUT returns 401 instead of 405

    This test ensures that user without permission for the object
    cannot obtain value for flag readonly
    """
    role_obj = all_models.Role.query.filter(
        all_models.Role.name == "Creator").one()

    factory = factories.get_model_factory(obj_type)

    with factories.single_commit():
      # create Global Creator
      person = factories.PersonFactory()
      person_id = person.id
      rbac_factories.UserRoleFactory(role=role_obj, person=person)

      # Create object
      obj = factory(title='a', readonly=True)
      obj_id = obj.id

    self.object_generator.api.set_user(all_models.Person.query.get(person_id))
    obj = get_model(obj_type).query.get(obj_id)
    resp = self.object_generator.api.put(obj, {'title': 'b'})

    self.assert403(resp)

  @ddt.data(
      ('System', True, False, 200, True),
      ('System', True, True, 405, False),
      ('System', False, False, 200, True),
      ('System', False, True, 405, False),
  )
  @ddt.unpack
  def test_delete(self, obj_type, is_external, readonly, exp_code,
                  exp_deleted):
    """Test {0} DELETE if readonly={1}"""

    factory = factories.get_model_factory(obj_type)
    with factories.single_commit():
      obj = factory(title='a', readonly=readonly)
      obj_id = obj.id

    if is_external:
      self.object_generator.api.login_as_external()
    else:
      self.object_generator.api.login_as_normal()

    obj = get_model(obj_type).query.get(obj_id)
    resp = self.object_generator.api.delete(obj)

    self.assertStatus(resp, exp_code)
    obj = get_model(obj_type).query.get(obj_id)
    if exp_deleted:
      self.assertIsNone(obj)
    else:
      self.assertIsNotNone(obj)

  @ddt.data('System')
  def test_403_if_delete_readonly_without_perms(self, obj_type):
    """Test {0} with readonly=True DELETE returns 401

    This test ensures that user without permission for the object
    cannot obtain value for flag readonly
    """

    role_obj = all_models.Role.query.filter(
        all_models.Role.name == "Creator").one()

    factory = factories.get_model_factory(obj_type)

    with factories.single_commit():
      # create Global Creator
      person = factories.PersonFactory()
      person_id = person.id
      rbac_factories.UserRoleFactory(role=role_obj, person=person)

      # Create object
      obj = factory(title='a', readonly=True)
      obj_id = obj.id

    self.object_generator.api.set_user(all_models.Person.query.get(person_id))
    obj = get_model(obj_type).query.get(obj_id)
    resp = self.object_generator.api.delete(obj)

    self.assert403(resp)
    obj = get_model(obj_type).query.get(obj_id)
    self.assertIsNotNone(obj)

  @ddt.data(
      ('System', False, 'Document', True, 201),
      ('System', False, 'Document', False, 201),
      ('System', True, 'Document', True, 405),
      ('System', True, 'Document', False, 405),
      ('System', False, 'Comment', True, 201),
      ('System', False, 'Comment', False, 201),
      ('System', True, 'Comment', True, 201),
      ('System', True, 'Comment', False, 201),
  )
  @ddt.unpack
  def test_relationship_post(self, obj_type, readonly, rel_obj_type, swap,
                             expected_code):
    """Test PUT relationship {0}.readonly={1}, related object type {2}"""

    factory = factories.get_model_factory(obj_type)
    rel_factory = factories.get_model_factory(rel_obj_type)
    with factories.single_commit():
      obj = factory(title='a', readonly=readonly)
      rel_obj = rel_factory()

    if swap:
      source, destination = rel_obj, obj
    else:
      source, destination = obj, rel_obj

    resp, _ = self.object_generator.generate_relationship(
        source=source, destination=destination
    )

    self.assertStatus(resp, expected_code)

  @ddt.data(
      ('System', False, 'Document', True, 200),
      ('System', False, 'Document', False, 200),
      ('System', True, 'Document', True, 405),
      ('System', True, 'Document', False, 405),
      ('System', False, 'Comment', True, 200),
      ('System', False, 'Comment', False, 200),
      ('System', True, 'Comment', True, 200),
      ('System', True, 'Comment', False, 200),
  )
  @ddt.unpack
  def test_relationship_delete(self, obj_type, readonly, rel_obj_type, swap,
                               expected_code):
    """Test DELETE relationship {0}.readonly={1}, related object type {2}"""

    factory = factories.get_model_factory(obj_type)
    rel_factory = factories.get_model_factory(rel_obj_type)
    with factories.single_commit():
      obj = factory(title='a', readonly=readonly)
      rel_obj = rel_factory()

      if swap:
        source, destination = rel_obj, obj
      else:
        source, destination = obj, rel_obj

      robj = factories.RelationshipFactory(source=source,
                                           destination=destination)

    resp = self.object_generator.api.delete(robj)

    self.assertStatus(resp, expected_code)

  @ddt.data(
      ("yes", "readonly system"),
      ("no", "non readonly system"),
  )
  @ddt.unpack
  def test_readonly_searchable(self, test_value, expected_title):
    """Test filtration by readonly attribute"""
    with factories.single_commit():
      factories.SystemFactory(title="readonly system", readonly=True)
      factories.SystemFactory(title="non readonly system")

    self.client.get("/login")
    actual_systems = self.simple_query(
        "System",
        expression=["readonly", "=", test_value]
    )
    self.assertEqual(
        [s.get("title") for s in actual_systems],
        [expected_title]
    )
Exemple #9
0
class TestCreator(TestCase):
    """ TestCreator """
    def setUp(self):
        super(TestCreator, self).setUp()
        self.api = Api()
        self.object_generator = ObjectGenerator()
        self.init_users()

    def init_users(self):
        """ Init users needed by the test cases """

        users = [("creator", "Creator"), ("admin", "Administrator")]
        self.users = {}
        for (name, role) in users:
            _, user = self.object_generator.generate_person(
                data={"name": name}, user_role=role)
            self.users[name] = user

    def test_admin_page_access(self):
        """Permissions to admin page."""
        for role, code in (("creator", 403), ("admin", 200)):
            self.api.set_user(self.users[role])
            self.assertEqual(self.api.client.get("/admin").status_code, code)

    def test_creator_can_crud(self):
        """ Test Basic create/read,update/delete operations """
        self.api.set_user(self.users["creator"])
        creator_id = self.users["creator"].id
        audit_id = factories.AuditFactory().id
        all_errors = []
        base_models = {
            "Control",
            "DataAsset",
            "Contract",
            "Requirement",
            "Policy",
            "Regulation",
            "Standard",
            "Document",
            "Facility",
            "Market",
            "Objective",
            "OrgGroup",
            "Vendor",
            "Product",
            "System",
            "Process",
            "Project",
            "AccessGroup",
            "Metric",
            "ProductGroup",
            "TechnologyEnvironment",
        }
        for model_singular in base_models:
            try:
                model = get_model(model_singular)
                table_singular = model._inflector.table_singular
                table_plural = model._inflector.table_plural
                # Test POST creation
                response, _ = self.object_generator.generate_object(
                    model,
                    data={
                        table_singular: {
                            "title": model_singular,
                            "context": None,
                            "documents_reference_url": "ref",
                            # ignored except for Document
                            "link": "https://example.com",
                            "contact": {
                                "type": "Person",
                                "id": creator_id
                            },
                            # this is ignored on everything but Issues
                            "audit": {
                                "id": audit_id,
                                "type": "Audit",
                            }
                        },
                    })

                if response.status_code != 201:
                    all_errors.append("{} post creation failed {} {}".format(
                        model_singular, response.status, response.data))
                    continue

                # Test GET when not owner
                obj_id = response.json.get(table_singular).get("id")
                response = self.api.get(model, obj_id)
                if response.status_code != 403:  # we are not onwers yet
                    all_errors.append(
                        "{} can retrieve object if not owner".format(
                            model_singular))
                    continue
                response = self.api.get_collection(model, obj_id)
                collection = response.json.get(
                    "{}_collection".format(table_plural)).get(table_plural)
                if collection:
                    all_errors.append(
                        "{} can retrieve object if not owner (collection)".
                        format(model_singular))
                    continue

                # Test GET when owner
                acr = all_models.AccessControlRole.query.filter_by(
                    object_type=model_singular, name="Admin").one()
                acl = all_models.AccessControlList.query.filter_by(
                    object_id=obj_id,
                    object_type=model_singular,
                    ac_role=acr,
                ).one()
                factories.AccessControlPersonFactory(
                    ac_list=acl,
                    person_id=creator_id,
                )

                response = self.api.get(model, obj_id)
                if response.status_code != 200:
                    all_errors.append("{} can't GET object {}".format(
                        model_singular, response.status))
                    continue

                # Test GET collection when owner
                response = self.api.get_collection(model, obj_id)
                collection = response.json.get(
                    "{}_collection".format(table_plural)).get(table_plural)
                if not collection:
                    all_errors.append(
                        "{} cannot retrieve object even if owner (collection)".
                        format(model_singular))
                    continue
            except:
                all_errors.append("{} exception thrown".format(model_singular))
                raise
        self.assertEqual(all_errors, [])

    def test_creator_search(self):
        """Test if creator can see the correct object while using the search api"""
        self.api.set_user(self.users['admin'])
        self.api.post(all_models.Regulation, {
            "regulation": {
                "title": "Admin regulation",
                "context": None
            },
        })
        self.api.set_user(self.users['creator'])
        acr_id = all_models.AccessControlRole.query.filter_by(
            object_type="Policy", name="Admin").first().id
        response = self.api.post(
            all_models.Policy, {
                "policy": {
                    "title":
                    "Creator Policy",
                    "context":
                    None,
                    "access_control_list": [
                        acl_helper.get_acl_json(acr_id,
                                                self.users["creator"].id)
                    ],
                },
            })
        response.json.get("policy").get("id")
        response, _ = self.api.search("Regulation,Policy")
        entries = response.json["results"]["entries"]
        self.assertEqual(len(entries), 1)
        self.assertEqual(entries[0]["type"], "Policy")
        response, _ = self.api.search("Regulation,Policy", counts=True)
        self.assertEqual(response.json["results"]["counts"]["Policy"], 1)
        self.assertEqual(response.json["results"]["counts"].get("Regulation"),
                         None)

    def _get_count(self, obj):
        """ Return the number of counts for the given object from search """
        response, _ = self.api.search(obj, counts=True)
        return response.json["results"]["counts"].get(obj)

    def test_creator_should_see_users(self):
        """ Test if creator can see all the users in the system """
        self.api.set_user(self.users['admin'])
        admin_count = self._get_count("Person")
        self.api.set_user(self.users['creator'])
        creator_count = self._get_count("Person")
        self.assertEqual(admin_count, creator_count)

    def test_relationships_access(self):
        """Check if creator cannot access relationship objects"""
        self.api.set_user(self.users['admin'])
        _, first_regulation = self.object_generator.generate_object(
            all_models.Regulation,
            data={"regulation": {
                "title": "Test regulation",
                "context": None
            }})
        _, second_regulation = self.object_generator.generate_object(
            all_models.Regulation,
            data={
                "regulation": {
                    "title": "Test regulation 2",
                    "context": None
                }
            })
        response, rel = self.object_generator.generate_relationship(
            first_regulation, second_regulation)
        relationship_id = rel.id
        self.assertEqual(response.status_code, 201)
        self.api.set_user(self.users['creator'])
        response = self.api.get_collection(all_models.Relationship,
                                           relationship_id)
        self.assertEqual(response.status_code, 200)
        num = len(response.json["relationships_collection"]["relationships"])
        self.assertEqual(num, 0)

    def test_revision_access(self):
        """Check if creator can access the right revision objects."""
        def gen(title, extra_data=None):
            """Generates requirement."""
            requirement_content = {"title": title, "context": None}
            if extra_data:
                requirement_content.update(**extra_data)
            return self.object_generator.generate_object(
                all_models.Requirement,
                data={"requirement": requirement_content})[1]

        def check(obj, expected):
            """Check that how many revisions of an object current user can see."""
            response = self.api.get_query(
                all_models.Revision,
                "resource_type={}&resource_id={}".format(obj.type, obj.id))
            self.assertEqual(response.status_code, 200)
            self.assertEqual(
                len(response.json['revisions_collection']['revisions']),
                expected)

        self.api.set_user(self.users["admin"])
        obj_1 = gen("Test Requirement 1")

        self.api.set_user(self.users["creator"])
        acr_id = all_models.AccessControlRole.query.filter_by(
            object_type="Requirement", name="Admin").first().id
        linked_acl = {
            "access_control_list":
            [acl_helper.get_acl_json(acr_id, self.users["creator"].id)],
        }
        check(obj_1, 0)
        obj_2 = gen("Test Requirement 2", linked_acl)
        obj2_acl = obj_2.access_control_list[0][1]
        check(obj_2, 1)
        check(obj2_acl, 1)

    @ddt.data("creator", "admin")
    def test_count_type_in_accordion(self, glob_role):
        """Return count of Persons in DB for side accordion."""
        self.api.set_user(self.users[glob_role])
        ocordion_api_person_count_link = (
            "/search?"
            "q=&types=Program%2CWorkflow_All%2C"
            "Audit%2CAssessment%2CIssue%2CRegulation%2C"
            "Policy%2CStandard%2CContract%2CRequirement%2CControl%2C"
            "Objective%2CPerson%2COrgGroup%2CVendor%2CAccessGroup%2CSystem%2C"
            "Process%2CDataAsset%2CProduct%2CProject%2CFacility%2C"
            "Market%2CRisk%2CThreat&counts_only=true&"
            "extra_columns=Workflow_All%3DWorkflow%2C"
            "Workflow_Active%3DWorkflow%2CWorkflow_Draft%3D"
            "Workflow%2CWorkflow_Inactive%3DWorkflow&contact_id=1&"
            "extra_params=Workflow%3Astatus%3DActive%3BWorkflow_Active"
            "%3Astatus%3DActive%3BWorkflow_Inactive%3Astatus%3D"
            "Inactive%3BWorkflow_Draft%3Astatus%3DDraft")
        resp = self.api.client.get(ocordion_api_person_count_link)
        self.assertIn("Person", resp.json["results"]["counts"])
        self.assertEqual(all_models.Person.query.count(),
                         resp.json["results"]["counts"]["Person"])

    @ddt.data(
        ("/api/revisions?resource_type={}&resource_id={}", 1),
        ("/api/revisions?source_type={}&source_id={}", 0),
        ("/api/revisions?destination_type={}&destination_id={}", 1),
    )
    @ddt.unpack
    def test_changelog_access(self, link, revision_count):
        """Test accessing changelog under GC user who is assigned to object"""
        with factories.single_commit():
            audit = factories.AuditFactory()
            asmnt = factories.AssessmentFactory(audit=audit)
            asmnt_id = asmnt.id
            factories.RelationshipFactory(source=audit, destination=asmnt)
            factories.AccessControlPersonFactory(
                ac_list=asmnt.acr_name_acl_map["Verifiers"],
                person=self.users["creator"],
            )

        self.api.set_user(self.users["creator"])
        response = self.api.client.get(link.format("Assessment", asmnt_id))
        self.assert200(response)
        self.assertEqual(
            len(
                response.json.get("revisions_collection",
                                  {}).get("revisions")), revision_count)

    @ddt.data(all_models.ControlCategory, all_models.ControlAssertion)
    def test_permissions_for_categories(self, category_model):
        """Test get collection for {0}."""
        self.api.set_user(self.users["creator"])
        resp = self.api.get_collection(category_model, None)
        plural_name = category_model._inflector.table_plural
        key_name = "{}_collection".format(plural_name)
        self.assertIn(key_name, resp.json)
        self.assertIn(plural_name, resp.json[key_name])
        collection = resp.json[key_name][plural_name]
        self.assertTrue(collection, "Collection shouldn't be empty")
Exemple #10
0
class TestWithReadOnlyAccessAPI(TestCase, query_helper.WithQueryApi):
    """Test WithReadOnlyAccess mixin"""
    def setUp(self):
        super(TestWithReadOnlyAccessAPI, self).setUp()
        self.object_generator = ObjectGenerator()
        self.object_generator.api.login_as_normal()

    @ddt.data(
        ('System', True),
        ('System', False),
        ('System', None),
        ('System', _NOT_SPECIFIED),
        ('System', "qwert"),
    )
    @ddt.unpack
    def test_readonly_ignored_on_post(self, obj_type, readonly):
        """Test flag readonly ignored on object {0} POST for body readonly={1}"""

        dct = dict()
        if readonly is not _NOT_SPECIFIED:
            dct['readonly'] = readonly
        resp, obj = self.object_generator.generate_object(
            get_model(obj_type),
            dct,
        )

        self.assertStatus(resp, 201)
        self.assertFalse(obj.readonly)

    @ddt.data(
        ('System', True, True),
        ('System', False, False),
        ('System', None, False),
        ('System', _NOT_SPECIFIED, False),
    )
    @ddt.unpack
    def test_readonly_set_on_post_as_external(self, obj_type, readonly,
                                              result):
        """Test flag readonly on {0} POST for body readonly={1} as external user"""

        dct = dict()
        if readonly is not _NOT_SPECIFIED:
            dct['readonly'] = readonly

        with self.object_generator.api.as_external():
            resp, obj = self.object_generator.generate_object(
                get_model(obj_type),
                dct,
            )
            obj_id = obj.id

        self.assertStatus(resp, 201)
        obj = get_model(obj_type).query.get(obj_id)
        self.assertEqual(obj.readonly, result)

    @ddt.data(
        ('System', False, False, 200),
        ('System', False, True, 200),
        ('System', False, None, 200),
        ('System', False, _NOT_SPECIFIED, 200),
        ('System', False, "qwerty", 200),
        ('System', True, False, 405),
        ('System', True, True, 405),
        ('System', True, None, 405),
        ('System', True, _NOT_SPECIFIED, 405),
        ('System', True, "qwerty", 405),
    )
    @ddt.unpack
    def test_put(self, obj_type, current, new, exp_code):
        """Test {0} PUT readonly={2} for current readonly={1}"""

        factory = factories.get_model_factory(obj_type)
        with factories.single_commit():
            obj = factory(title='a', readonly=current)
            obj_id = obj.id

        data = {'title': 'b'}
        if new is not _NOT_SPECIFIED:
            data['readonly'] = new

        resp = self.object_generator.api.put(obj, data)

        self.assertStatus(resp, exp_code)
        obj = get_model(obj_type).query.get(obj_id)
        self.assertEqual(obj.readonly, current)

    @ddt.data(
        ('System', False, False, 200, False),
        ('System', False, True, 200, True),
        ('System', False, None, 200, False),
        ('System', False, _NOT_SPECIFIED, 200, False),
        ('System', True, False, 200, False),
        ('System', True, True, 200, True),
        ('System', True, None, 200, True),
        ('System', True, _NOT_SPECIFIED, 200, True),
    )
    @ddt.unpack
    def test_put_as_external(self, obj_type, current, new, exp_code,
                             exp_readonly):
        """Test {0} PUT readonly={2} for current readonly={1} for external user"""

        factory = factories.get_model_factory(obj_type)
        with factories.single_commit():
            obj = factory(title='a', readonly=current)
            obj_id = obj.id

        data = {'title': 'b'}
        if new is not _NOT_SPECIFIED:
            data['readonly'] = new

        with self.object_generator.api.as_external():
            obj = get_model(obj_type).query.get(obj_id)
            resp = self.object_generator.api.put(obj, data)

        self.assertStatus(resp, exp_code)
        obj = get_model(obj_type).query.get(obj_id)
        self.assertEqual(obj.readonly, exp_readonly)

    @ddt.data('System')
    def test_403_if_put_readonly_without_perms(self, obj_type):
        """Test {0} with readonly=True PUT returns 401 instead of 405

    This test ensures that user without permission for the object
    cannot obtain value for flag readonly
    """
        role_obj = all_models.Role.query.filter(
            all_models.Role.name == "Creator").one()

        factory = factories.get_model_factory(obj_type)

        with factories.single_commit():
            # create Global Creator
            person = factories.PersonFactory()
            person_id = person.id
            rbac_factories.UserRoleFactory(role=role_obj, person=person)

            # Create object
            obj = factory(title='a', readonly=True)
            obj_id = obj.id

        self.object_generator.api.set_user(
            all_models.Person.query.get(person_id))
        obj = get_model(obj_type).query.get(obj_id)
        resp = self.object_generator.api.put(obj, {'title': 'b'})

        self.assert403(resp)

    @ddt.data(
        ('System', True, False, 200, True),
        ('System', True, True, 405, False),
        ('System', False, False, 200, True),
        ('System', False, True, 405, False),
    )
    @ddt.unpack
    def test_delete(self, obj_type, is_external, readonly, exp_code,
                    exp_deleted):
        """Test {0} DELETE if readonly={1}"""

        factory = factories.get_model_factory(obj_type)
        with factories.single_commit():
            obj = factory(title='a', readonly=readonly)
            obj_id = obj.id

        if is_external:
            self.object_generator.api.login_as_external()
        else:
            self.object_generator.api.login_as_normal()

        obj = get_model(obj_type).query.get(obj_id)
        resp = self.object_generator.api.delete(obj)

        self.assertStatus(resp, exp_code)
        obj = get_model(obj_type).query.get(obj_id)
        if exp_deleted:
            self.assertIsNone(obj)
        else:
            self.assertIsNotNone(obj)

    @ddt.data('System')
    def test_403_if_delete_readonly_without_perms(self, obj_type):
        """Test {0} with readonly=True DELETE returns 401

    This test ensures that user without permission for the object
    cannot obtain value for flag readonly
    """

        role_obj = all_models.Role.query.filter(
            all_models.Role.name == "Creator").one()

        factory = factories.get_model_factory(obj_type)

        with factories.single_commit():
            # create Global Creator
            person = factories.PersonFactory()
            person_id = person.id
            rbac_factories.UserRoleFactory(role=role_obj, person=person)

            # Create object
            obj = factory(title='a', readonly=True)
            obj_id = obj.id

        self.object_generator.api.set_user(
            all_models.Person.query.get(person_id))
        obj = get_model(obj_type).query.get(obj_id)
        resp = self.object_generator.api.delete(obj)

        self.assert403(resp)
        obj = get_model(obj_type).query.get(obj_id)
        self.assertIsNotNone(obj)

    @ddt.data(
        ('System', False, 'Document', True, 201),
        ('System', False, 'Document', False, 201),
        ('System', True, 'Document', True, 405),
        ('System', True, 'Document', False, 405),
        ('System', False, 'Comment', True, 201),
        ('System', False, 'Comment', False, 201),
        ('System', True, 'Comment', True, 201),
        ('System', True, 'Comment', False, 201),
    )
    @ddt.unpack
    def test_relationship_post(self, obj_type, readonly, rel_obj_type, swap,
                               expected_code):
        """Test PUT relationship {0}.readonly={1}, related object type {2}"""

        factory = factories.get_model_factory(obj_type)
        rel_factory = factories.get_model_factory(rel_obj_type)
        with factories.single_commit():
            obj = factory(title='a', readonly=readonly)
            rel_obj = rel_factory()

        if swap:
            source, destination = rel_obj, obj
        else:
            source, destination = obj, rel_obj

        resp, _ = self.object_generator.generate_relationship(
            source=source, destination=destination)

        self.assertStatus(resp, expected_code)

    @ddt.data(
        ('System', False, 'Document', True, 200),
        ('System', False, 'Document', False, 200),
        ('System', True, 'Document', True, 405),
        ('System', True, 'Document', False, 405),
        ('System', False, 'Comment', True, 200),
        ('System', False, 'Comment', False, 200),
        ('System', True, 'Comment', True, 200),
        ('System', True, 'Comment', False, 200),
    )
    @ddt.unpack
    def test_relationship_delete(self, obj_type, readonly, rel_obj_type, swap,
                                 expected_code):
        """Test DELETE relationship {0}.readonly={1}, related object type {2}"""

        factory = factories.get_model_factory(obj_type)
        rel_factory = factories.get_model_factory(rel_obj_type)
        with factories.single_commit():
            obj = factory(title='a', readonly=readonly)
            rel_obj = rel_factory()

            if swap:
                source, destination = rel_obj, obj
            else:
                source, destination = obj, rel_obj

            robj = factories.RelationshipFactory(source=source,
                                                 destination=destination)

        resp = self.object_generator.api.delete(robj)

        self.assertStatus(resp, expected_code)

    @ddt.data(
        ("yes", "readonly system"),
        ("no", "non readonly system"),
    )
    @ddt.unpack
    def test_readonly_searchable(self, test_value, expected_title):
        """Test filtration by readonly attribute"""
        with factories.single_commit():
            factories.SystemFactory(title="readonly system", readonly=True)
            factories.SystemFactory(title="non readonly system")

        self.client.get("/login")
        actual_systems = self.simple_query(
            "System", expression=["readonly", "=", test_value])
        self.assertEqual([s.get("title") for s in actual_systems],
                         [expected_title])
Exemple #11
0
class TestCreator(TestCase):
  """ TestCreator """

  def setUp(self):
    super(TestCreator, self).setUp()
    self.api = Api()
    self.object_generator = ObjectGenerator()
    self.init_users()

  def init_users(self):
    """ Init users needed by the test cases """

    users = [("creator", "Creator"), ("admin", "Administrator")]
    self.users = {}
    for (name, role) in users:
      _, user = self.object_generator.generate_person(
          data={"name": name}, user_role=role)
      self.users[name] = user

  def test_admin_page_access(self):
    """Permissions to admin page."""
    for role, code in (("creator", 403), ("admin", 200)):
      self.api.set_user(self.users[role])
      self.assertEqual(self.api.client.get("/admin").status_code, code)

  def test_creator_can_crud(self):
    """ Test Basic create/read,update/delete operations """
    self.api.set_user(self.users["creator"])
    creator_id = self.users["creator"].id
    audit_id = factories.AuditFactory().id
    all_errors = []
    base_models = {
        "DataAsset", "Contract", "Requirement",
        "Policy", "Regulation", "Standard", "Document", "Facility",
        "Market", "Objective", "OrgGroup", "Vendor", "Product",
        "System", "Process", "Project", "AccessGroup",
        "Metric", "ProductGroup", "TechnologyEnvironment",
    }
    for model_singular in base_models:
      try:
        model = get_model(model_singular)
        table_singular = model._inflector.table_singular
        table_plural = model._inflector.table_plural
        # Test POST creation
        response, _ = self.object_generator.generate_object(
            model,
            data={
                table_singular: {
                    "title": model_singular,
                    "context": None,
                    "documents_reference_url": "ref",
                    # ignored except for Document
                    "link": "https://example.com",
                    "contact": {
                        "type": "Person",
                        "id": creator_id
                    },
                    # this is ignored on everything but Issues
                    "audit": {
                        "id": audit_id,
                        "type": "Audit",
                    }
                },
            }
        )

        if response.status_code != 201:
          all_errors.append("{} post creation failed {} {}".format(
              model_singular, response.status, response.data))
          continue

        # Test GET when not owner
        obj_id = response.json.get(table_singular).get("id")
        response = self.api.get(model, obj_id)
        if response.status_code != 403:  # we are not onwers yet
          all_errors.append(
              "{} can retrieve object if not owner".format(model_singular))
          continue
        response = self.api.get_collection(model, obj_id)
        collection = response.json.get(
            "{}_collection".format(table_plural)).get(table_plural)
        if collection:
          all_errors.append(
              "{} can retrieve object if not owner (collection)"
              .format(model_singular))
          continue

        # Test GET when owner
        acr = all_models.AccessControlRole.query.filter_by(
            object_type=model_singular,
            name="Admin"
        ).one()
        acl = all_models.AccessControlList.query.filter_by(
            object_id=obj_id,
            object_type=model_singular,
            ac_role=acr,
        ).one()
        factories.AccessControlPersonFactory(
            ac_list=acl,
            person_id=creator_id,
        )

        response = self.api.get(model, obj_id)
        if response.status_code != 200:
          all_errors.append("{} can't GET object {}".format(
              model_singular, response.status))
          continue

        # Test GET collection when owner
        response = self.api.get_collection(model, obj_id)
        collection = response.json.get(
            "{}_collection".format(table_plural)).get(table_plural)
        if not collection:
          all_errors.append(
              "{} cannot retrieve object even if owner (collection)"
              .format(model_singular))
          continue
      except:
        all_errors.append("{} exception thrown".format(model_singular))
        raise
    self.assertEqual(all_errors, [])

  def test_creator_search(self):
    """Test if creator can see the correct object while using the search api"""
    self.api.set_user(self.users['admin'])
    self.api.post(all_models.Regulation, {
        "regulation": {"title": "Admin regulation", "context": None},
    })
    self.api.set_user(self.users['creator'])
    acr_id = all_models.AccessControlRole.query.filter_by(
        object_type="Policy",
        name="Admin"
    ).first().id
    response = self.api.post(all_models.Policy, {
        "policy": {
            "title": "Creator Policy",
            "context": None,
            "access_control_list": [
                acl_helper.get_acl_json(acr_id, self.users["creator"].id)],
        },
    })
    response.json.get("policy").get("id")
    response, _ = self.api.search("Regulation,Policy")
    entries = response.json["results"]["entries"]
    self.assertEqual(len(entries), 1)
    self.assertEqual(entries[0]["type"], "Policy")
    response, _ = self.api.search("Regulation,Policy", counts=True)
    self.assertEqual(response.json["results"]["counts"]["Policy"], 1)
    self.assertEqual(
        response.json["results"]["counts"].get("Regulation"), None)

  def _get_count(self, obj):
    """ Return the number of counts for the given object from search """
    response, _ = self.api.search(obj, counts=True)
    return response.json["results"]["counts"].get(obj)

  def test_creator_should_see_users(self):
    """ Test if creator can see all the users in the system """
    self.api.set_user(self.users['admin'])
    admin_count = self._get_count("Person")
    self.api.set_user(self.users['creator'])
    creator_count = self._get_count("Person")
    self.assertEqual(admin_count, creator_count)

  def test_relationships_access(self):
    """Check if creator cannot access relationship objects"""
    self.api.set_user(self.users['admin'])
    _, first_regulation = self.object_generator.generate_object(
        all_models.Regulation,
        data={"regulation": {"title": "Test regulation", "context": None}}
    )
    _, second_regulation = self.object_generator.generate_object(
        all_models.Regulation,
        data={"regulation": {"title": "Test regulation 2", "context": None}}
    )
    response, rel = self.object_generator.generate_relationship(
        first_regulation, second_regulation
    )
    relationship_id = rel.id
    self.assertEqual(response.status_code, 201)
    self.api.set_user(self.users['creator'])
    response = self.api.get_collection(all_models.Relationship,
                                       relationship_id)
    self.assertEqual(response.status_code, 200)
    num = len(response.json["relationships_collection"]["relationships"])
    self.assertEqual(num, 0)

  def test_revision_access(self):
    """Check if creator can access the right revision objects."""

    def gen(title, extra_data=None):
      """Generates requirement."""
      requirement_content = {"title": title, "context": None}
      if extra_data:
        requirement_content.update(**extra_data)
      return self.object_generator.generate_object(
          all_models.Requirement,
          data={"requirement": requirement_content}
      )[1]

    def check(obj, expected):
      """Check that how many revisions of an object current user can see."""
      response = self.api.get_query(
          all_models.Revision,
          "resource_type={}&resource_id={}".format(obj.type, obj.id)
      )
      self.assertEqual(response.status_code, 200)
      self.assertEqual(
          len(response.json['revisions_collection']['revisions']),
          expected
      )

    self.api.set_user(self.users["admin"])
    obj_1 = gen("Test Requirement 1")

    self.api.set_user(self.users["creator"])
    acr_id = all_models.AccessControlRole.query.filter_by(
        object_type="Requirement",
        name="Admin"
    ).first().id
    linked_acl = {
        "access_control_list": [
            acl_helper.get_acl_json(acr_id, self.users["creator"].id)],
    }
    check(obj_1, 0)
    obj_2 = gen("Test Requirement 2", linked_acl)
    obj2_acl = obj_2.access_control_list[0][1]
    check(obj_2, 1)
    check(obj2_acl, 1)

  @ddt.data("creator", "admin")
  def test_count_type_in_accordion(self, glob_role):
    """Return count of Persons in DB for side accordion."""
    self.api.set_user(self.users[glob_role])
    ocordion_api_person_count_link = (
        "/search?"
        "q=&types=Program%2CWorkflow_All%2C"
        "Audit%2CAssessment%2CIssue%2CRegulation%2C"
        "Policy%2CStandard%2CContract%2CRequirement%2CControl%2C"
        "Objective%2CPerson%2COrgGroup%2CVendor%2CAccessGroup%2CSystem%2C"
        "Process%2CDataAsset%2CProduct%2CProject%2CFacility%2C"
        "Market%2CRisk%2CThreat&counts_only=true&"
        "extra_columns=Workflow_All%3DWorkflow%2C"
        "Workflow_Active%3DWorkflow%2CWorkflow_Draft%3D"
        "Workflow%2CWorkflow_Inactive%3DWorkflow&contact_id=1&"
        "extra_params=Workflow%3Astatus%3DActive%3BWorkflow_Active"
        "%3Astatus%3DActive%3BWorkflow_Inactive%3Astatus%3D"
        "Inactive%3BWorkflow_Draft%3Astatus%3DDraft"
    )
    resp = self.api.client.get(ocordion_api_person_count_link)
    self.assertIn("Person", resp.json["results"]["counts"])
    self.assertEqual(all_models.Person.query.count(),
                     resp.json["results"]["counts"]["Person"])

  @ddt.data(
      ("/api/revisions?resource_type={}&resource_id={}", 1),
      ("/api/revisions?source_type={}&source_id={}", 0),
      ("/api/revisions?destination_type={}&destination_id={}", 1),
  )
  @ddt.unpack
  def test_changelog_access(self, link, revision_count):
    """Test accessing changelog under GC user who is assigned to object"""
    with factories.single_commit():
      audit = factories.AuditFactory()
      asmnt = factories.AssessmentFactory(audit=audit)
      asmnt_id = asmnt.id
      factories.RelationshipFactory(source=audit, destination=asmnt)
      factories.AccessControlPersonFactory(
          ac_list=asmnt.acr_name_acl_map["Verifiers"],
          person=self.users["creator"],
      )

    self.api.set_user(self.users["creator"])
    response = self.api.client.get(link.format("Assessment", asmnt_id))
    self.assert200(response)
    self.assertEqual(
        len(response.json.get("revisions_collection", {}).get("revisions")),
        revision_count
    )

  @staticmethod
  def _query_revisions(api, resource_type, resource_id):
    """Helper function querying revisions related to particular object."""
    return api.send_request(
        api.client.post,
        api_link="/query",
        data=[{
            "object_name": "Revision",
            "type": "ids",
            "filters": {
                "expression": {
                    "left": {
                        "left": {
                            "left": "resource_type",
                            "op": {"name": "="},
                            "right": resource_type,
                        },
                        "op": {"name": "AND"},
                        "right": {
                            "left": "resource_id",
                            "op": {"name": "="},
                            "right": resource_id,
                        },
                    },
                    "op": {"name": "OR"},
                    "right": {
                        "left": {
                            "left": {
                                "left": "source_type",
                                "op": {"name": "="},
                                "right": resource_type,
                            },
                            "op": {"name": "AND"},
                            "right": {
                                "left": "source_id",
                                "op": {"name": "="},
                                "right": resource_id,
                            }
                        },
                        "op": {"name": "OR"},
                        "right": {
                            "left": {
                                "left": "destination_type",
                                "op": {"name": "="},
                                "right": resource_type,
                            },
                            "op": {"name": "AND"},
                            "right": {
                                "left": "destination_id",
                                "op": {"name": "="},
                                "right": resource_id,
                            }
                        }
                    }
                },
            },
        }],
    )

  def test_revision_access_query(self):
    """Test GC assigned to obj can access revisions through query API."""
    with factories.single_commit():
      program = factories.ProgramFactory()
      audit = factories.AuditFactory()
      factories.RelationshipFactory(
          source=audit,
          destination=program,
      )
      factories.AccessControlPersonFactory(
          ac_list=audit.acr_name_acl_map["Auditors"],
          person=self.users["creator"],
      )

    audit_id = audit.id
    self.api.set_user(self.users["creator"])
    response = self._query_revisions(self.api, audit.type, audit_id)

    self.assert200(response)
    self.assertEqual(response.json[0]["Revision"]["count"], 2)

  def test_rev_access_query_no_right(self):
    """Test GC has no access to revisions of objects it has no right on."""
    with factories.single_commit():
      program = factories.ProgramFactory()
      audit = factories.AuditFactory()
      factories.RelationshipFactory(
          source=audit,
          destination=program,
      )

    audit_id = audit.id
    self.api.set_user(self.users["creator"])
    response = self._query_revisions(self.api, audit.type, audit_id)

    self.assert200(response)
    self.assertEqual(response.json[0]["Revision"]["count"], 0)
class TestWithReadOnlyAccessAPI(TestCase):
  """Test WithReadOnlyAccess mixin"""

  def setUp(self):
    super(TestWithReadOnlyAccessAPI, self).setUp()
    self.object_generator = ObjectGenerator()
    self.object_generator.api.login_as_normal()

  @ddt.data(
      ('System', True),
      ('System', False),
      ('System', None),
      ('System', "qwert"),
  )
  @ddt.unpack
  def test_readonly_ignored_on_post(self, obj_type, readonly):
    """Test flag readonly ignored on object {0} POST for body readonly={1}"""

    dct = dict()
    if readonly is not None:
      dct['readonly'] = readonly
    resp, obj = self.object_generator.generate_object(
        get_model(obj_type),
        {'readonly': readonly},
    )

    self.assertStatus(resp, 201)

    self.assertFalse(obj.readonly)

  @ddt.data(
      ('System', False, False, 200),
      ('System', False, True, 200),
      ('System', False, None, 200),
      ('System', True, False, 405),
      ('System', True, True, 405),
      ('System', True, None, 405),
  )
  @ddt.unpack
  def test_put(self, obj_type, current, new, exp_code):
    """Test {0} PUT readonly={2} for current readonly={1}"""

    factory = factories.get_model_factory(obj_type)
    with factories.single_commit():
      obj = factory(title='a', readonly=current)
      obj_id = obj.id

    data = {'title': 'b'}
    if new is not None:
      data['readonly'] = new

    resp = self.object_generator.api.put(obj, data)

    self.assertStatus(resp, exp_code)
    obj = get_model(obj_type).query.get(obj_id)
    self.assertEqual(obj.readonly, current)

  @ddt.data('System')
  def test_403_if_put_readonly_without_perms(self, obj_type):
    """Test {0} with readonly=True PUT returns 401 instead of 405

    This test ensures that user without permission for the object
    cannot obtain value for flag readonly
    """
    role_obj = all_models.Role.query.filter(
        all_models.Role.name == "Creator").one()

    factory = factories.get_model_factory(obj_type)

    with factories.single_commit():
      # create Global Creator
      person = factories.PersonFactory()
      person_id = person.id
      rbac_factories.UserRoleFactory(role=role_obj, person=person)

      # Create object
      obj = factory(title='a', readonly=True)
      obj_id = obj.id

    self.object_generator.api.set_user(all_models.Person.query.get(person_id))
    obj = get_model(obj_type).query.get(obj_id)
    resp = self.object_generator.api.put(obj, {'title': 'b'})

    self.assert403(resp)

  @ddt.data(
      ('System', False, 200, True),
      ('System', True, 405, False),
  )
  @ddt.unpack
  def test_delete(self, obj_type, readonly, exp_code, exp_deleted):
    """Test {0} DELETE if readonly={1}"""

    factory = factories.get_model_factory(obj_type)
    with factories.single_commit():
      obj = factory(title='a', readonly=readonly)
      obj_id = obj.id

    resp = self.object_generator.api.delete(obj)

    self.assertStatus(resp, exp_code)
    obj = get_model(obj_type).query.get(obj_id)
    if exp_deleted:
      self.assertIsNone(obj)
    else:
      self.assertIsNotNone(obj)

  @ddt.data('System')
  def test_403_if_delete_readonly_without_perms(self, obj_type):
    """Test {0} with readonly=True DELETE returns 401

    This test ensures that user without permission for the object
    cannot obtain value for flag readonly
    """

    role_obj = all_models.Role.query.filter(
        all_models.Role.name == "Creator").one()

    factory = factories.get_model_factory(obj_type)

    with factories.single_commit():
      # create Global Creator
      person = factories.PersonFactory()
      person_id = person.id
      rbac_factories.UserRoleFactory(role=role_obj, person=person)

      # Create object
      obj = factory(title='a', readonly=True)
      obj_id = obj.id

    self.object_generator.api.set_user(all_models.Person.query.get(person_id))
    obj = get_model(obj_type).query.get(obj_id)
    resp = self.object_generator.api.delete(obj)

    self.assert403(resp)
    obj = get_model(obj_type).query.get(obj_id)
    self.assertIsNotNone(obj)

  @ddt.data(
      ('System', False, 'Document', True, 201),
      ('System', False, 'Document', False, 201),
      ('System', True, 'Document', True, 405),
      ('System', True, 'Document', False, 405),
      ('System', False, 'Comment', True, 201),
      ('System', False, 'Comment', False, 201),
      ('System', True, 'Comment', True, 201),
      ('System', True, 'Comment', False, 201),
  )
  @ddt.unpack
  def test_relationship_post(self, obj_type, readonly, rel_obj_type, swap,
                             expected_code):
    """Test PUT relationship {0}.readonly={1}, related object type {2}"""

    factory = factories.get_model_factory(obj_type)
    rel_factory = factories.get_model_factory(rel_obj_type)
    with factories.single_commit():
      obj = factory(title='a', readonly=readonly)
      rel_obj = rel_factory()

    if swap:
      source, destination = rel_obj, obj
    else:
      source, destination = obj, rel_obj

    resp, _ = self.object_generator.generate_relationship(
        source=source, destination=destination
    )

    self.assertStatus(resp, expected_code)

  @ddt.data(
      ('System', False, 'Document', True, 200),
      ('System', False, 'Document', False, 200),
      ('System', True, 'Document', True, 405),
      ('System', True, 'Document', False, 405),
      ('System', False, 'Comment', True, 200),
      ('System', False, 'Comment', False, 200),
      ('System', True, 'Comment', True, 200),
      ('System', True, 'Comment', False, 200),
  )
  @ddt.unpack
  def test_relationship_delete(self, obj_type, readonly, rel_obj_type, swap,
                               expected_code):
    """Test DELETE relationship {0}.readonly={1}, related object type {2}"""

    factory = factories.get_model_factory(obj_type)
    rel_factory = factories.get_model_factory(rel_obj_type)
    with factories.single_commit():
      obj = factory(title='a', readonly=readonly)
      rel_obj = rel_factory()

      if swap:
        source, destination = rel_obj, obj
      else:
        source, destination = obj, rel_obj

      robj = factories.RelationshipFactory(source=source,
                                           destination=destination)

    resp = self.object_generator.api.delete(robj)

    self.assertStatus(resp, expected_code)
Exemple #13
0
class TestResource(TestCase):
  """
  Test /search REST API
  """

  def setUp(self):
    super(TestResource, self).setUp()
    self.api = Api()
    self.object_generator = ObjectGenerator()
    self.create_objects()

  def create_objects(self):
    """Create objects to be searched.

    Creates five controls and makes relationships.
    0   1   2   3   4
    |---|   |---|   |
    |-------|-------|
    """
    self.objects = [
        self.object_generator.generate_object(Control)[1].id
        for _ in xrange(5)
    ]
    self.objects = Control.eager_query().filter(
        Control.id.in_(self.objects)
    ).all()
    for src, dst in [(0, 1), (0, 2), (2, 3), (2, 4)]:
      self.object_generator.generate_relationship(
          self.objects[src], self.objects[dst]
      )

  def search(self, *args, **kwargs):
    res, _ = self.api.search(*args, **kwargs)
    return res.json["results"]["entries"]

  def test_search_all(self):
    """Test search for all objects of a type."""
    res, _ = self.api.search("Control")
    self.assertEqual(len(res.json["results"]["entries"]), 5)

  def test_search_query(self):
    """Test search with query by title."""
    entries = self.search("Control", query=self.objects[0].title)
    self.assertEqual({entry["id"] for entry in entries},
                     {self.objects[0].id})

  def test_search_relevant(self):
    """Test search with 'relevant to' single object."""
    relevant_objects = "Control:{}".format(self.objects[0].id)
    entries = self.search("Control", relevant_objects=relevant_objects)
    self.assertEqual({entry["id"] for entry in entries},
                     {self.objects[i].id for i in [1, 2]})

  def test_search_relevant_multi(self):
    """Test search with 'relevant to' multiple objects."""
    ids = ",".join("Control:{}".format(self.objects[i].id) for i in (0, 3))
    entries = self.search("Control", relevant_objects=ids)
    self.assertEqual({entry["id"] for entry in entries},
                     {self.objects[2].id})

  def test_search_fail_with_terms_none(self):
    """Test search to fail with BadRequest (400 Error) when terms are None."""
    query = '/search?types={}&counts_only={}'.format("Control", False)
    response = self.api.client.get(query)
    self.assert400(response)
    self.assertEqual(response.json['message'], 'Query parameter "q" '
                     'specifying search terms must be provided.')