コード例 #1
0
class TestPermissionsLoading(TestMemcacheBase):
  """Test user permissions loading."""

  def setUp(self):
    super(TestPermissionsLoading, self).setUp()
    self.api = Api()
    self.generator = generator.ObjectGenerator()

    self.control_id = factories.ControlFactory().id

    _, user = self.generator.generate_person(user_role="Creator")
    self.api.set_user(user)

  def test_permissions_loading(self):
    """Test if permissions created only once for GET requests."""
    with mock.patch(
        "ggrc_basic_permissions.store_results_into_memcache",
        side_effect=ggrc_basic_permissions.store_results_into_memcache
    ) as store_perm:
      self.api.get(all_models.Control, self.control_id)
      store_perm.assert_called_once()
      store_perm.call_count = 0

      # On second GET permissions should be loaded from memcache
      # but not created from scratch.
      self.api.get(all_models.Control, self.control_id)
      store_perm.assert_not_called()
コード例 #2
0
class TestAssigneeRBAC(TestRBAC):
  """TestAssigneeRBAC tests if users get correct permissions on objects
  where he is has assignee role"""
  def setUp(self):
    super(TestAssigneeRBAC, self).setUp()
    self.api = Api()
    self.set_up_people()
    self.assignee_roles = {
        role_name: role_id
        for role_id, role_name in get_custom_roles_for("Assessment").items()
        if role_name in ["Assignees", "Creators", "Verifiers"]
    }

  def test_mapped_regulations_read(self):
    """Test if creators can CRUD mapped Regulations and Objective snapshots."""
    self.api.set_user(self.people.get("Editor"))
    with factories.single_commit():
      audit = factories.AuditFactory()
      assessment = factories.AssessmentFactory(audit=audit)
      factories.AccessControlPersonFactory(
          ac_list=assessment.acr_name_acl_map["Creators"],
          person=self.people.get("Editor"),
      )
      factories.AccessControlPersonFactory(
          ac_list=assessment.acr_name_acl_map["Assignees"],
          person=self.people.get("Creator"),
      )
      factories.RelationshipFactory(source=audit, destination=assessment)
      control = factories.ControlFactory()
      objective = factories.ObjectiveFactory()
      regulation = factories.RegulationFactory()
      snapshots = self._create_snapshots(
          audit, [control, objective, regulation]
      )
      for snapshot in snapshots:
        factories.RelationshipFactory(source=audit, destination=snapshot)
      factories.RelationshipFactory(
          source=snapshots[0], destination=snapshots[1]
      )
      factories.RelationshipFactory(
          source=snapshots[2], destination=snapshots[0]
      )
      factories.RelationshipFactory(
          source=assessment, destination=snapshots[0]
      )

    self.api.set_user(self.people.get("Creator"))
    for snapshot in snapshots:
      db.session.add(snapshot)
      response = self.api.get(type(snapshot), snapshot.id)
      self.assertEqual(
          response.status_code, 200,
          "Cannot GET mapped object. Received {}".format(response.status)
      )
      db.session.add(snapshot)
      response = self.api.delete(snapshot)
      self.assertEqual(
          response.status_code, 403,
          "Can DELETE mapped object. Received {}".format(response.status)
      )
コード例 #3
0
class TestAccessControlRBAC(TestRBAC):
  """TestAccessControlRBAC tests if users get correct permissions on objects
     from the access control table"""

  def setUp(self):
    super(TestAccessControlRBAC, self).setUp()
    self.api = Api()
    self.set_up_people()
    self.set_up_acl_object()

  @ddt.data("Creator", "Reader", "Editor")
  def test_acl_object_cru(self, name):
    """Test if {0} can CRUD an object with all permissions"""
    control_id = self.control.id
    person = self.people.get(name)
    role_id = self.all_acr.id
    db.session.add(person)
    self.api.set_user(person)
    response = self.api.get(all_models.Control, control_id)
    assert response.status_code == 200, \
        "{} cannot GET object from acl. Received {}".format(
            name, response.status)
    acl = response.json["control"]["access_control_list"]
    assert len(response.json["control"]["access_control_list"]) == 3, \
        "ACL in control does not include all people {}".format(acl)

    assert acl[0].get("ac_role_id", None) == role_id, \
        "ACL list does not include role id {}".format(acl)
コード例 #4
0
class TestPersonProfilePermissions(TestCase):
  """Test PersonProfile."""

  def setUp(self):
    super(TestPersonProfilePermissions, self).setUp()
    self.generator = Generator()
    self.api = Api()
    self.object_generator = ObjectGenerator()
    self.init_users()

  def init_users(self):
    """Init user with different roles."""
    users = [("reader", "Reader"),
             ("editor", "Editor"),
             ("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

  @ddt.data("reader", "editor", "admin", "creator")
  def test_permissions(self, name):
    """Test permissions for user roles."""
    user = all_models.Person.query.get(self.users[name].id)
    profile = all_models.PersonProfile.query.join(
        all_models.PersonProfile.person
    ).filter_by(
        email=user.email
    ).one()
    self.api.set_user(self.users[name])
    response = self.api.get(all_models.PersonProfile, profile.id)
    self.assert200(response)

    new_date = "2018-05-20 22:05:17"
    response = self.api.put(profile, {
        "people_profiles": {
            "id": profile.id,
            "last_seen_whats_new": new_date,
        },
    })
    self.assert200(response)

    response = self.api.delete(profile)
    if name == "admin":
      self.assert200(response)
    else:
      self.assert403(response)
コード例 #5
0
class TestReader(TestCase):
  """Test Assignable RBAC"""

  def setUp(self):
    super(TestReader, self).setUp()
    self.audit_id = factories.AuditFactory().id
    self.generator = Generator()
    self.api = Api()
    self.object_generator = ObjectGenerator()
    self.init_users()
    self.init_assignable()

  def init_users(self):
    """ Init users needed by the test cases """
    users = [("creator", "Creator"), ("reader", "Reader"),
             ("editor", "Editor"), ("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 init_assignable(self):
    """Creates the assignable object used by all the tests"""
    self.api.set_user(self.users["editor"])
    response = self.api.post(all_models.Assessment, {
        "assessment": {
            "title": "Assessment",
            "context": None,
            "audit": {
                "id": self.audit_id,
                "type": "Audit"
            }
        }
    })
    obj_id = response.json.get("assessment").get("id")
    self.assertEqual(response.status_code, 201, "Error setting up Assessment")
    self.obj_json = response.json
    self.obj = all_models.Assessment.query.get(obj_id)

  def _add_creator(self, asmnt, user):
    """Helper method for creating assignees on an object"""
    acr = all_models.AccessControlRole.query.filter(
        all_models.AccessControlRole.object_type == "Assessment",
        all_models.AccessControlRole.name == "Creators",
    ).first()
    return self.api.put(asmnt, {
        "access_control_list": [acl_helper.get_acl_json(acr.id, user.id)]
    })

  def test_basic_with_no_assignee(self):
    """Editor creates an Assessment, but doesn't assign Reader/Creator as
       assignee. Reader should have Read access, Creator should have no access
    """

    # Reader should have read access, but shouldn't be allowed to edit or
    # create another assingee
    self.api.set_user(self.users["reader"])
    response = self.api.get(all_models.Assessment, self.obj.id)
    self.assertEqual(response.status_code, 200)
    response = self.api.put(self.obj, self.obj_json)
    self.assertEqual(response.status_code, 403)
    response = self._add_creator(self.obj, self.users["reader"])
    self.assertEqual(response.status_code, 403)

    # Creator should have no access. We skip the put request because we can't
    # get the object etag.
    self.api.set_user(self.users["creator"])
    response = self.api.get(all_models.Assessment, self.obj.id)
    self.assertEqual(response.status_code, 403)
    response = self._add_creator(self.obj, self.users["reader"])
    self.assertEqual(response.status_code, 403)

  def test_basic_with_assignee(self):
    """Test if Reader/Creator have CRUD access once they become assignees"""

    # Admin adds reader as an assignee
    self.api.set_user(self.users["admin"])
    response = self._add_creator(self.obj, self.users["reader"])
    self.assertEqual(response.status_code, 200)

    # Reader is now allowed to update the object
    self.api.set_user(self.users["reader"])
    response = self.api.get(all_models.Assessment, self.obj.id)
    self.assertEqual(response.status_code, 200)
    response = self.api.put(self.obj, response.json)
    self.assertEqual(response.status_code, 200)

    # Reader adds creator as an assignee
    response = self._add_creator(self.obj, self.users["creator"])
    self.assertEqual(response.status_code, 200)

    # Creator now has CRUD access
    self.api.set_user(self.users["creator"])
    response = self.api.get(all_models.Assessment, self.obj.id)
    self.assertEqual(response.status_code, 200)
    response = self.api.put(self.obj, response.json)

    # Creator should even be allowed to add new assignees
    response = self._add_creator(self.obj, self.users["admin"])
    self.assertEqual(response.status_code, 200)

  def test_read_of_mapped_objects(self):
    """Test if assignees get Read access on all mapped objects"""

    # Editor creates a System object and maps it to the assignable object
    self.api.set_user(self.users["editor"])
    response = self.api.post(all_models.System, {
        "system": {
            "title": "System",
            "context": None,
        }
    })
    system_id = response.json.get("system").get("id")
    system = all_models.System.query.get(system_id)
    self.api.post(all_models.Relationship, {
        "relationship": {"source": {
            "id": self.obj.id,
            "type": "Assessment"
        }, "destination": {
            "id": system_id,
            "type": "System"
        }, "context": None},
    })

    # Since creator is not an assignee she should not have access to any of the
    # two objects
    self.api.set_user(self.users["creator"])
    response = self.api.get(all_models.Assessment, self.obj.id)
    self.assertEqual(response.status_code, 403)
    response = self.api.get(all_models.System, system_id)
    self.assertEqual(response.status_code, 403)

    # Editor adds creator as an assignee
    self.api.set_user(self.users["editor"])
    response = self._add_creator(self.obj, self.users["creator"])
    self.assertEqual(response.status_code, 200)

    # Creator should now have read access on the mapped object
    self.api.set_user(self.users["creator"])
    response = self.api.get(all_models.System, system_id)
    self.assertEqual(response.status_code, 403)

    # But he should still not be allowed to update
    response = self.api.put(system, response.json)
    self.assertEqual(response.status_code, 403)
コード例 #6
0
ファイル: test_audit_rbac.py プロジェクト: zidarsk8/ggrc-core
class TestPermissionsOnAssessmentTemplate(TestCase):
  """ Test check permissions for ProgramEditor on

  get and post assessment_temaplte action"""

  def setUp(self):
    super(TestPermissionsOnAssessmentTemplate, self).setUp()
    self.api = Api()
    self.generator = ObjectGenerator()
    _, program = self.generator.generate_object(all_models.Program)
    program_id = program.id
    _, self.editor = self.generator.generate_person(
        user_role="Creator"
    )
    role = perms.all_models.Role.query.filter(
        perms.all_models.Role.name == "ProgramEditor"
    ).first()
    self.generator.generate_user_role(
        self.editor,
        role,
        all_models.Program.query.get(program_id)
    )
    _, audit = self.generator.generate_object(
        all_models.Audit,
        {
            "title": "Audit",
            "program": {"id": program_id},
            "status": "Planned"
        },
    )
    audit_id = audit.id

    generated_at = self.generator.generate_object(
        all_models.AssessmentTemplate,
        {
            "title": "Template",
            "_NON_RELEVANT_OBJ_TYPES": {},
            "_objectTypes": {},
            "audit": {"id": audit.id},
            "audit_title": audit.title,
            "people_value": [],
            "default_people": {
                "assessors": "Object Owners",
                "verifiers": "Object Owners",
            },
            "context": {"id": audit.context.id},
        }
    )
    self.assessment_template_resp, assessment_template = generated_at
    assessment_template_id = assessment_template.id
    self.api.set_user(self.editor)
    self.perms_data = self.api.client.get("/permissions").json
    self.audit = all_models.Audit.query.get(audit_id)
    self.assessment_template = all_models.AssessmentTemplate.query.get(
        assessment_template_id)

  def test_post_action(self):
    """Test create action on AssessmentTemplate created by api"""
    data = [{
        "assessment_template": {
            "_NON_RELEVANT_OBJ_TYPES": {},
            "_objectTypes": {},
            "audit": {"id": self.audit.id},
            "audit_title": self.audit.title,
            "people_value": [],
            "default_people": {
                "assessors": "Object Owners",
                "verifiers": "Object Owners",
            },
            "context": {"id": self.audit.context.id},
            "title": "123",
        }
    }]
    self.api.set_user(self.editor)
    resp = self.api.post(all_models.AssessmentTemplate, data)
    self.assert200(resp)

  def test_get_action(self):
    """Test read action on AssessmentTemplate created by api"""
    resp = self.api.get(all_models.AssessmentTemplate,
                        self.assessment_template.id)
    self.assert200(resp)

  def test_put_action(self):
    """Test update action on AssessmentTemplate created by api"""
    to_update = copy.deepcopy(self.assessment_template_resp.json)
    new_title = "new_{}".format(self.assessment_template.title)
    to_update['assessment_template']['title'] = new_title
    resp = self.api.put(self.assessment_template, to_update)
    self.assert200(resp)
    assessment_tmpl = all_models.AssessmentTemplate.query.get(
        self.assessment_template.id
    )
    self.assertEqual(new_title, assessment_tmpl.title)

  def test_delete_action(self):
    """Test delete action on AssessmentTemplate created by api"""
    resp = self.api.delete(self.assessment_template)
    self.assert200(resp)
    self.assertFalse(all_models.AssessmentTemplate.query.filter(
        all_models.AssessmentTemplate == self.assessment_template.id).all())
コード例 #7
0
ファイル: test_audit_rbac.py プロジェクト: zidarsk8/ggrc-core
class TestAuditRBAC(TestCase):
  """Test audit RBAC"""

  CSV_DIR = join(abspath(dirname(__file__)), "test_csvs")

  @classmethod
  def setUpClass(cls):
    TestCase.clear_data()
    cls.response = cls._import_file("audit_rbac.csv")
    cls.people = all_models.Person.eager_query().all()
    cls.audit = all_models.Audit.eager_query().first()
    sources = set(r.source for r in cls.audit.related_sources)
    destinations = set(r.destination for r in cls.audit.related_destinations)
    related = [obj for obj in sources.union(destinations)
               if not isinstance(obj, all_models.Person)]
    cls.related_objects = related

  def setUp(self):
    """Imports test_csvs/audit_rbac.csv needed by the tests"""
    self._check_csv_response(self.response, {})
    self.api = Api()
    self.client.get("/login")

  def read(self, objects):
    """Attempt to do a GET request for every object in the objects list"""
    responses = []
    for obj in objects:
      status_code = self.api.get(obj.__class__, obj.id).status_code
      responses.append((obj.type, status_code))
    return responses

  def update(self, objects):
    """Attempt to do a PUT request for every object in the objects list"""
    responses = []
    for obj in objects:
      response = self.api.get(obj.__class__, obj.id)
      status_code = response.status_code
      if response.status_code == 200:
        status_code = self.api.put(obj, response.json).status_code
      responses.append((obj.type, status_code))
    return responses

  def call_api(self, method, expected_statuses):
    """Calls the REST api with a given method and returns a list of
       status_codes that do not match the expected_statuses dict"""
    all_errors = []
    for person in self.people:
      self.api.set_user(person)
      responses = method(self.related_objects + [self.audit])
      for type_, code in responses:
        if code != expected_statuses[person.email]:
          all_errors.append("{} does not have {} access to {} ({})".format(
              person.email, method.__name__, type_, code))
    return all_errors

  def test_read_access_on_mapped(self):
    """Test if people have read access to mapped objects.

    All users except [email protected] should have read access."""
    expected_statuses = defaultdict(lambda: 200)
    for exception in ("*****@*****.**",):
      expected_statuses[exception] = 403
    errors = self.call_api(self.read, expected_statuses)
    assert not errors, "\n".join(errors)

  def test_update_access_on_mapped(self):
    """Test if people have upate access to mapped objects.

    All users except [email protected], [email protected], [email protected],
    [email protected] should have update access."""
    expected_statuses = defaultdict(lambda: 200)
    for exception in ("*****@*****.**", "*****@*****.**",
                      "*****@*****.**", "*****@*****.**"):
      expected_statuses[exception] = 403
    errors = self.call_api(self.update, expected_statuses)
    assert not errors, "\n".join(errors)
コード例 #8
0
class TestReviewApi(TestCase):
  """Base TestCase class proposal api tests."""

  def setUp(self):
    super(TestReviewApi, self).setUp()
    self.api = Api()
    self.api.client.get("/login")
    self.generator = generator.ObjectGenerator()

  def test_simple_get(self):
    """Test simple get"""
    with factories.single_commit():
      risk = factories.RiskFactory()
      review = factories.ReviewFactory(
          email_message="test email message",
          notification_type="email",
          reviewable=risk,
          status=all_models.Review.STATES.UNREVIEWED,
      )
    resp = self.api.get(all_models.Review, review.id)
    self.assert200(resp)
    self.assertIn("review", resp.json)
    resp_review = resp.json["review"]
    self.assertEqual(all_models.Review.STATES.UNREVIEWED,
                     resp_review["status"])
    self.assertEqual(all_models.Review.NotificationTypes.EMAIL_TYPE,
                     resp_review["notification_type"])
    self.assertEqual("test email message",
                     resp_review["email_message"])

  def test_collection_get(self):
    """Test simple collection get"""
    with factories.single_commit():
      review1 = factories.ReviewFactory(
          status=all_models.Review.STATES.UNREVIEWED
      )
      review2 = factories.ReviewFactory(
          status=all_models.Review.STATES.REVIEWED
      )

    resp = self.api.get_collection(all_models.Review,
                                   [review1.id, review2.id])
    self.assert200(resp)
    self.assertIn("reviews_collection", resp.json)
    self.assertIn("reviews", resp.json["reviews_collection"])
    self.assertEquals(2, len(resp.json["reviews_collection"]["reviews"]))

  def test_create_review(self):
    """Create review via API, check that single relationship is created"""
    program = factories.ProgramFactory()
    program_id = program.id
    resp = self.api.post(
        all_models.Review,
        {
            "review": {
                "reviewable": {
                    "type": program.type,
                    "id": program.id,
                },
                "context": None,
                "notification_type": "email",
                "status": all_models.Review.STATES.UNREVIEWED,
                "access_control_list": build_reviewer_acl()
            },
        },
    )
    self.assertEqual(201, resp.status_code)
    review_id = resp.json["review"]["id"]
    review = all_models.Review.query.get(review_id)
    self.assertEqual(all_models.Review.STATES.UNREVIEWED, review.status)
    self.assertEqual(program.type, review.reviewable_type)
    self.assertEqual(program_id, review.reviewable_id)

    control_review_rel_count = all_models.Relationship.query.filter(
        all_models.Relationship.source_id == review.id,
        all_models.Relationship.source_type == review.type,
        all_models.Relationship.destination_id == program_id,
        all_models.Relationship.destination_type == program.type,
    ).union(
        all_models.Relationship.query.filter(
            all_models.Relationship.destination_id == review.id,
            all_models.Relationship.destination_type == review.type,
            all_models.Relationship.source_id == program_id,
            all_models.Relationship.source_type == program.type,
        )
    ).count()
    self.assertEqual(1, control_review_rel_count)

  def test_delete_review(self):
    """Test delete review via API"""
    with factories.single_commit():
      risk = factories.RiskFactory()
      risk_id = risk.id
      review = factories.ReviewFactory(reviewable=risk)
      review_id = review.id
    resp = self.api.delete(review)
    self.assert200(resp)
    review = all_models.Review.query.get(review_id)
    risk = all_models.Risk.query.get(risk_id)

    self.assertIsNone(review)
    self.assertEquals(0, len(risk.related_objects(_types=["Review"])))

  def test_last_reviewed(self):
    """last_reviewed_by, last_reviewed_by should be set if reviewed"""
    risk = factories.RiskFactory()
    resp, review = self.generator.generate_object(
        all_models.Review,
        {
            "reviewable": {
                "type": risk.type,
                "id": risk.id,
            },
            "context": None,
            "status": all_models.Review.STATES.UNREVIEWED,
            "access_control_list": build_reviewer_acl(),
            "notification_type": all_models.Review.NotificationTypes.EMAIL_TYPE
        },
    )
    review_id = review.id
    resp = self.api.put(
        review,
        {
            "status": all_models.Review.STATES.REVIEWED,
        },
    )
    self.assert200(resp)
    self.assertIsNotNone(resp.json["review"]["last_reviewed_by"])
    self.assertIsNotNone(resp.json["review"]["last_reviewed_at"])

    review = all_models.Review.query.get(review_id)
    self.assertIsNotNone(review.last_reviewed_by)
    self.assertIsNotNone(review.last_reviewed_at)

  def test_reviewable_revisions(self):
    """Check that proper revisions are created"""
    program = factories.ProgramFactory()
    resp, review = self.generator.generate_object(
        all_models.Review,
        {
            "reviewable": {
                "type": program.type,
                "id": program.id,
            },
            "context": None,
            "status": all_models.Review.STATES.UNREVIEWED,
            "access_control_list": build_reviewer_acl(),
            "notification_type": all_models.Review.NotificationTypes.EMAIL_TYPE
        },
    )
    program_id = program.id
    reviewable = review.reviewable

    program_revisions = all_models.Revision.query.filter_by(
        resource_id=program_id,
        resource_type=program.type
    ).order_by(
        all_models.Revision.id,
    ).all()
    self.assertEquals(2, len(program_revisions))
    self.assertEquals(all_models.Review.STATES.UNREVIEWED,
                      program_revisions[0].content["review_status"])
    self.assertEquals(all_models.Review.STATES.UNREVIEWED,
                      program_revisions[1].content["review_status"])
    resp = self.api.put(
        review,
        {
            "status": all_models.Review.STATES.REVIEWED,
        },
    )
    self.assert200(resp)

    program_revisions = all_models.Revision.query.filter_by(
        resource_id=program_id,
        resource_type=program.type
    ).order_by(
        all_models.Revision.id,
    ).all()
    self.assertEquals(3, len(program_revisions))
    self.assertEquals(all_models.Review.STATES.REVIEWED,
                      program_revisions[2].content["review_status"])

    resp = self.api.put(
        reviewable,
        {
            "description": "some new description"
        }
    )
    self.assert200(resp)

    program_revisions = all_models.Revision.query.filter_by(
        resource_id=program_id,
        resource_type=program.type
    ).order_by(
        all_models.Revision.id,
    ).all()
    self.assertEquals(4, len(program_revisions))
    self.assertEquals(all_models.Review.STATES.UNREVIEWED,
                      program_revisions[3].content["review_status"])
コード例 #9
0
class TestCreatorProgram(TestCase):
  """Set up necessary objects and test Creator role with Program roles"""

  def setUp(self):
    super(TestCreatorProgram, self).setUp()
    self.generator = Generator()
    self.api = Api()
    self.object_generator = ObjectGenerator()
    self.init_users()
    self.init_roles()
    self.init_test_cases()
    self.objects = {}

  def init_test_cases(self):
    """ Create a dict of all possible test cases """
    self.test_cases = {
        "notmapped": {
            "objects": {
                "program": {
                    "get": 403,
                    "put": 403,
                    "delete": 403
                },
                "mapped_object": {
                    "get": 403,
                    "put": 403,
                    "delete": 403
                },
                "unrelated": {
                    "get": 403,
                    "put": 403,
                    "delete": 403,
                    "map": 403,
                }
            },
        },
        "mapped": {
            "objects": {
                "program": {
                    "get": 403,
                    "put": 403,
                    "delete": 403
                },
                "mapped_object": {
                    "get": 403,
                    "put": 403,
                    "delete": 403
                },
                "unrelated": {
                    "get": 403,
                    "put": 403,
                    "delete": 403,
                    "map": 403,
                }
            }
        },
        "ProgramReader": {
            "program_role": "ProgramReader",
            "objects": {
                "program": {
                    "get": 200,
                    "put": 403,
                    "delete": 403
                },
                "mapped_object": {
                    "get": 200,
                    "put": 403,
                    "delete": 403
                },
                "unrelated": {
                    "get": 403,
                    "put": 403,
                    "delete": 403,
                    "map": 403,
                }
            }
        },
        "ProgramOwner": {
            "program_role": "ProgramOwner",
            "objects": {
                "program": {
                    "get": 200,
                    "put": 200,
                    "delete": 200
                },
                "mapped_object": {
                    "get": 200,
                    "put": 200,
                    "delete": 200,
                },
                "unrelated": {
                    "get": 403,
                    "put": 403,
                    "delete": 403,
                    "map": 403,
                }
            }
        },
        "ProgramEditor": {
            "program_role": "ProgramEditor",
            "objects": {
                "program": {
                    "get": 200,
                    "put": 200,
                    "delete": 200
                },
                "mapped_object": {
                    "get": 200,
                    "put": 200,
                    "delete": 200
                },
                "unrelated": {
                    "get": 403,
                    "put": 403,
                    "delete": 403,
                    "map": 403,
                }
            }
        },
    }

  def init_roles(self):
    """ Create a delete request for the given object """
    response = self.api.get_query(all_models.Role, "")
    self.roles = {}
    for role in response.json.get("roles_collection").get("roles"):
      self.roles[role.get("name")] = role

  def init_users(self):
    """ Create users used by test cases """
    users = [
        ("creator", "Creator"),
        ("notmapped", "Creator"),
        ("mapped", "Creator"),
        ("ProgramReader", "Creator"),
        ("ProgramEditor", "Creator"),
        ("ProgramOwner", "Creator")]
    self.people = {}
    for (name, role) in users:
      _, user = self.object_generator.generate_person(
          data={"name": name}, user_role=role)
      self.people[name] = user

  def delete(self, obj):
    """ Create a delete request for the given object """
    return self.api.delete(obj).status_code

  def get(self, obj):
    """ Create a get request for the given object """
    return self.api.get(obj.__class__, obj.id).status_code

  def put(self, obj):
    """ Create a put request for the given object """
    response = self.api.get(obj.__class__, obj.id)
    if response.status_code == 200:
      return self.api.put(obj, response.json).status_code
    else:
      return response.status_code

  def map(self, dest):
    """ Map src to dest """
    response = self.api.post(all_models.Relationship, {
        "relationship": {"source": {
            "id": self.objects["program"].id,
            "type": self.objects["program"].type,
        }, "destination": {
            "id": dest.id,
            "type": dest.type
        }, "context": None},
    })
    return response.status_code

  def init_objects(self, test_case_name):
    """ Create a Program and a Mapped object for a given test case """
    # Create a program
    test_case = self.test_cases[test_case_name]
    creator = self.people.get('creator')
    self.api.set_user(creator)
    random_title = factories.random_str()
    response = self.api.post(all_models.Program, {
        "program": {"title": random_title, "context": None},
    })
    self.assertEqual(response.status_code, 201)
    context_id = response.json.get("program").get("context").get("id")
    program_id = response.json.get("program").get("id")

    # Use admin owner role to map it with system
    acr_id = all_models.AccessControlRole.query.filter_by(
        object_type="System",
        name="Admin"
    ).first().id
    self.objects["program"] = all_models.Program.query.get(program_id)

    # Create an object:
    for obj in ("mapped_object", "unrelated"):
      random_title = factories.random_str()
      response = self.api.post(all_models.System, {
          "system": {
              "title": random_title,
              "context": None,
              "access_control_list": [{
                  "person": {
                      "id": creator.id,
                      "type": "Person",
                  },
                  "ac_role_id": acr_id,
                  "context": None
              }],
          },
      })
      self.assertEqual(response.status_code, 201)
      system_id = response.json.get("system").get("id")
      self.objects[obj] = all_models.System.query.get(system_id)

    # Map Object to Program
    response = self.api.post(all_models.Relationship, {
        "relationship": {"source": {
            "id": program_id,
            "type": "Program"
        }, "destination": {
            "id": self.objects["mapped_object"].id,
            "type": "System"
        }, "context": None},
    })
    self.assertEqual(response.status_code, 201)

    # Map people to Program:
    if test_case_name != "notmapped":
      person = self.people.get(test_case_name)
      response = self.api.post(all_models.ObjectPerson, {"object_person": {
          "person": {
              "id": person.id,
              "type": "Person",
              "href": "/api/people/{}".format(person.id),
          }, "personable": {
              "type": "Program",
              "href": "/api/programs/{}".format(program_id),
              "id": program_id,
          }, "context": {
              "type": "Context",
              "id": context_id,
              "href": "/api/contexts/{}".format(context_id)
          }}})

    # Add roles to mapped users:
    if "program_role" in test_case:
      person = self.people.get(test_case_name)
      role = self.roles[test_case["program_role"]]
      response = self.api.post(all_models.UserRole, {"user_role": {
          "person": {
              "id": person.id,
              "type": "Person",
              "href": "/api/people/{}".format(person.id),
          }, "role": {
              "type": "Role",
              "href": "/api/roles/{}".format(role["id"]),
              "id": role["id"],
          }, "context": {
              "type": "Context",
              "id": context_id,
              "href": "/api/contexts/{}".format(context_id)
          }}})
      self.assertEqual(response.status_code, 201)

  def test_creator_program_roles(self):
    """ Test creator role with all program scoped roles """
    # Check permissions based on test_cases:
    errors = []
    for test_case in self.test_cases:
      self.init_objects(test_case)
      person = self.people.get(test_case)
      objects = self.test_cases.get(test_case).get('objects')
      self.api.set_user(person)
      for obj in ("unrelated", "mapped_object", "program"):
        actions = objects[obj]
        for action in ("map", "get", "put", "delete"):
          # reset sesion:
          db.session.commit()
          if action not in actions:
            continue
          func = getattr(self, action)
          res = func(self.objects[obj])
          if res != actions[action]:
            errors.append(
                "{}: Tried {} on {}, but received {} instead of {}".format(
                    test_case, action, obj, res, actions[action]))
      # Try mapping
    self.assertEqual(errors, [])
コード例 #10
0
class TestCreatorAudit(TestCase):
  """Set up necessary objects and test Creator role with Audit roles"""

  def setUp(self):
    super(TestCreatorAudit, self).setUp()
    self.generator = Generator()
    self.api = Api()
    self.object_generator = ObjectGenerator()
    self.init_users()
    self.init_roles()
    self.init_test_cases()
    self.objects = {}

  def init_test_cases(self):
    """Create a dict of all possible test cases."""
    self.test_cases = {
        "Auditor": {
            "audit_role": "Auditor",
            "objects": {
                "audit": {
                    "get": 200,
                    "put": 403,
                    "delete": 403
                },
                "mapped_Issue": {
                    "get": 200,
                    "put": 200,
                    "delete": 200
                },
                "unrelated_Issue": {
                    "get": 403,
                    "put": 403,
                    "delete": 403,
                    "map": 403,
                },
                "mapped_Assessment": {
                    "get": 200,
                    "put": 200,
                    "delete": 200
                },
                "unrelated_Assessment": {
                    "get": 403,
                    "put": 403,
                    "delete": 403,
                    "map": 403,
                }
            }
        },
    }

  def init_roles(self):
    """Create a delete request for the given object."""
    response = self.api.get_query(all_models.Role, "")
    self.roles = {}
    for role in response.json.get("roles_collection").get("roles"):
      self.roles[role.get("name")] = role

  def init_users(self):
    """Create users used by test cases."""
    self.people = {}
    for name in ["creator", "notmapped", "mapped", "Auditor"]:
      _, user = self.object_generator.generate_person(
          data={"name": name}, user_role="Creator")
      self.people[name] = user

    _, user = self.object_generator.generate_person(
        data={"name": "editor"}, user_role="Editor")
    self.people["editor"] = user

  def delete(self, obj):
    """Create a delete request for the given object.

    Args:
        obj (model instance): target object to delete
    Returns:
        int: http response status code
    """
    return self.api.delete(obj).status_code

  def get(self, obj):
    """Create a get request for the given object.

    Args:
        obj (model instance): target object to get
    Returns:
        int: http response status code
    """
    return self.api.get(obj.__class__, obj.id).status_code

  def put(self, obj):
    """Create a put request for the given object.

    Args:
        obj (model instance): target object to put
    Returns:
        int: http response status code
    """
    response = self.api.get(obj.__class__, obj.id)
    if response.status_code == 200:
      return self.api.put(obj, response.json).status_code
    else:
      return response.status_code

  def map(self, dest):
    """Map audit to dest.

    Args:
        dest (model instance): target object to map to the audit
    Returns:
        int: http response status code
    """
    response = self.api.post(all_models.Relationship, {
        "relationship": {"source": {
            "id": self.objects["audit"].id,
            "type": self.objects["audit"].type,
        }, "destination": {
            "id": dest.id,
            "type": dest.type
        }, "context": None},
    })
    return response.status_code

  def init_objects(self, test_case_name):
    """Create a Program, an Audit, and a Mapped object for the test case.

    Args:
        test_case_name (string): test case to init for
    """
    # Create a program
    dummy_audit = factories.AuditFactory()
    unrelated_audit = {
        "type": "Audit",
        "context_id": dummy_audit.context.id,
        "id": dummy_audit.id,
    }
    test_case = self.test_cases[test_case_name]
    editor = self.people.get('editor')
    self.api.set_user(editor)
    random_title = factories.random_str()
    response = self.api.post(all_models.Program, {
        "program": {"title": random_title, "context": None},
    })
    self.assertEqual(response.status_code, 201)
    program_id = response.json.get("program").get("id")
    self.objects["program"] = all_models.Program.query.get(program_id)
    response = self.api.post(all_models.Audit, {
        "audit": {
            "title": random_title + " audit",
            'program': {'id': program_id},
            "status": "Planned",
            "context": None
        }
    })
    self.assertEqual(response.status_code, 201)
    context = response.json.get("audit").get("context")
    audit_id = response.json.get("audit").get("id")
    self.objects["audit"] = all_models.Audit.query.get(audit_id)
    audits = {
        "mapped": {
            "type": "Audit",
            "context_id": context["id"],
            "id": audit_id,
        },
        "unrelated": unrelated_audit,
    }

    for prefix, audit_dict in audits.items():
      random_title = factories.random_str()

      response = self.api.post(all_models.Issue, {
          "issue": {
              "title": random_title,
              "context": {
                  "type": "Context",
                  "id": audit_dict["context_id"],
              },
              "audit": audit_dict,
          },
      })
      self.assertEqual(response.status_code, 201)
      issue_id = response.json.get("issue").get("id")
      self.objects[prefix + "_Issue"] = all_models.Issue.query.get(issue_id)

      response = self.api.post(all_models.Assessment, {
          "assessment": {
              "title": random_title,
              "context": {
                  "type": "Context",
                  "id": audit_dict["context_id"],
              },
              "audit": audit_dict,
          },
      })
      self.assertEqual(response.status_code, 201)
      assessment_id = response.json.get("assessment").get("id")
      self.objects[prefix + "_Assessment"] = \
          all_models.Assessment.query.get(assessment_id)

    self.assertEqual(self.map(self.objects["mapped_Issue"]), 201)
    self.assertEqual(self.map(self.objects["mapped_Assessment"]), 201)

    # Add roles to mapped users:
    if "audit_role" in test_case:
      person = self.people.get(test_case_name)
      role = self.roles[test_case["audit_role"]]
      response = self.api.post(all_models.UserRole, {"user_role": {
          "person": {
              "id": person.id,
              "type": "Person",
              "href": "/api/people/{}".format(person.id),
          }, "role": {
              "type": "Role",
              "href": "/api/roles/{}".format(role["id"]),
              "id": role["id"],
          }, "context": {
              "type": "Context",
              "id": context.get("id"),
              "href": "/api/contexts/{}".format(context.get("id"))
          }}})
      self.assertEqual(response.status_code, 201)

  def test_creator_audit_roles(self):
    """ Test creator role with all audit scoped roles """
    # Check permissions based on test_cases:
    errors = []
    for test_case in self.test_cases:
      self.init_objects(test_case)
      person = self.people.get(test_case)
      objects = self.test_cases.get(test_case).get('objects')
      self.api.set_user(person)
      for obj, actions in objects.iteritems():
        for action in ("map", "get", "put", "delete"):
          if action not in actions:
            continue
          # reset sesion:
          db.session.commit()
          func = getattr(self, action)
          res = func(self.objects[obj])
          if res != actions[action]:
            errors.append(
                "{}: Tried {} on {}, but received {} instead of {}".format(
                    test_case, action, obj, res, actions[action]))

    self.assertEqual(errors, [])
コード例 #11
0
ファイル: test_reader.py プロジェクト: zdqf/ggrc-core
class TestReader(TestCase):
    """ Test reader role """
    def setUp(self):
        super(TestReader, self).setUp()
        self.generator = Generator()
        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",
            "Clause",
            "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.api.post(
                    model,
                    {
                        table_singular: {
                            "title": model_singular,
                            "context": None,
                            "documents_reference_url": "ref",
                            "link":
                            "https://example.com",  # ignored except 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'])
        _, obj_0 = self.generator.generate(all_models.Regulation, "regulation",
                                           {
                                               "regulation": {
                                                   "title": "Test regulation",
                                                   "context": None
                                               },
                                           })
        _, obj_1 = self.generator.generate(
            all_models.Regulation, "regulation", {
                "regulation": {
                    "title": "Test regulation 2",
                    "context": None
                },
            })
        response, rel = self.generator.generate(
            all_models.Relationship, "relationship", {
                "relationship": {
                    "source": {
                        "id": obj_0.id,
                        "type": "Regulation"
                    },
                    "destination": {
                        "id": obj_1.id,
                        "type": "Regulation"
                    },
                    "context": None
                },
            })
        relationship_id = rel.id
        self.assertEqual(response.status_code, 201)
        self.api.set_user(self.users['reader'])
        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, 1)

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

        response, _ = self.generator.generate(
            all_models.Relationship, "relationship", {
                "relationship": {
                    "destination": {
                        "id": program.id,
                        "type": "Program"
                    },
                    "source": {
                        "id": control.id,
                        "type": "Control"
                    },
                    "context": {
                        "id": program.context.id,
                        "type": "context"
                    }
                },
            })
        self.assertEqual(response.status_code, 403)

    @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.assertEqual(response.status_code, 403)

    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"])
コード例 #12
0
class TestCreator(TestCase):
    """ TestCreator """
    def setUp(self):
        super(TestCreator, self).setUp()
        self.generator = Generator()
        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):
        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 = set([
            "Control", "DataAsset", "Contract", "Policy", "Regulation",
            "Standard", "Document", "Facility", "Market", "Objective",
            "OrgGroup", "Vendor", "Product", "Clause", "System", "Process",
            "Project", "AccessGroup"
        ])
        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.api.post(model, {
                    table_singular: {
                        "title": model_singular,
                        "context": None,
                        "reference_url": "ref",
                        "contact": {
                            "type": "Person",
                            "id": creator_id,
                        },
                        "audit": {  # this is ignored on everything but Issues
                            "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 len(collection) != 0:
                    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").first()
                factories.AccessControlListFactory(object_id=obj_id,
                                                   object_type=model_singular,
                                                   ac_role=acr,
                                                   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 len(collection) == 0:
                    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": [{
                        "person": {
                            "id": self.users["creator"].id,
                            "type": "Person",
                        },
                        "ac_role_id": acr_id,
                        "context": None
                    }],
                },
            })
        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'])
        _, obj_0 = self.generator.generate(all_models.Regulation, "regulation",
                                           {
                                               "regulation": {
                                                   "title": "Test regulation",
                                                   "context": None
                                               },
                                           })
        _, obj_1 = self.generator.generate(
            all_models.Regulation, "regulation", {
                "regulation": {
                    "title": "Test regulation 2",
                    "context": None
                },
            })
        response, rel = self.generator.generate(
            all_models.Relationship, "relationship", {
                "relationship": {
                    "source": {
                        "id": obj_0.id,
                        "type": "Regulation"
                    },
                    "destination": {
                        "id": obj_1.id,
                        "type": "Regulation"
                    },
                    "context": None
                },
            })
        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):
            section_content = {"title": title, "context": None}
            section_content.update(**extra_data) if extra_data else None
            return self.generator.generate(all_models.Section, "section",
                                           {"section": section_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 Section 1")

        self.api.set_user(self.users["creator"])
        acr_id = all_models.AccessControlRole.query.filter_by(
            object_type="Section", name="Admin").first().id
        linked_acl = {
            "access_control_list": [{
                "person": {
                    "id": self.users["creator"].id,
                    "type": "Person",
                },
                "ac_role_id": acr_id,
                "context": None
            }]
        }
        check(obj_1, 0)
        obj_2 = gen("Test Section 2", linked_acl)
        obj2_acl = obj_2.access_control_list[0]
        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%2CClause%2CSection%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"])
コード例 #13
0
class TestCreatorProgram(TestCase):
  """Set up necessary objects and test Creator role with Program roles"""

  def setUp(self):
    TestCase.setUp(self)
    self.generator = Generator()
    self.api = Api()
    self.object_generator = ObjectGenerator()
    self.init_users()
    self.init_roles()
    self.init_test_cases()
    self.objects = {}

  def init_test_cases(self):
    """ Create a dict of all possible test cases """
    self.test_cases = {
        "notmapped": {
            "objects": {
                "program": {
                    "get": 403,
                    "put": 403,
                    "delete": 403
                },
                "mapped_object": {
                    "get": 403,
                    "put": 403,
                    "delete": 403
                },
                "unrelated": {
                    "get": 403,
                    "put": 403,
                    "delete": 403,
                    "map": 403,
                }
            },
        },
        "mapped": {
            "objects": {
                "program": {
                    "get": 403,
                    "put": 403,
                    "delete": 403
                },
                "mapped_object": {
                    "get": 403,
                    "put": 403,
                    "delete": 403
                },
                "unrelated": {
                    "get": 403,
                    "put": 403,
                    "delete": 403,
                    "map": 403,
                }
            }
        },
        "ProgramReader": {
            "program_role": "ProgramReader",
            "objects": {
                "program": {
                    "get": 200,
                    "put": 403,
                    "delete": 403
                },
                "mapped_object": {
                    "get": 200,
                    "put": 403,
                    "delete": 403
                },
                "unrelated": {
                    "get": 403,
                    "put": 403,
                    "delete": 403,
                    "map": 403,
                }
            }
        },
        "ProgramOwner": {
            "program_role": "ProgramOwner",
            "objects": {
                "program": {
                    "get": 200,
                    "put": 200,
                    "delete": 200
                },
                "mapped_object": {
                    "get": 200,
                    "put": 200,
                    "delete": 200,
                },
                "unrelated": {
                    "get": 403,
                    "put": 403,
                    "delete": 403,
                    "map": 403,
                }
            }
        },
        "ProgramEditor": {
            "program_role": "ProgramEditor",
            "objects": {
                "program": {
                    "get": 200,
                    "put": 200,
                    "delete": 200
                },
                "mapped_object": {
                    "get": 200,
                    "put": 200,
                    "delete": 200
                },
                "unrelated": {
                    "get": 403,
                    "put": 403,
                    "delete": 403,
                    "map": 403,
                }
            }
        },
    }

  def init_roles(self):
    """ Create a delete request for the given object """
    response = self.api.get_query(all_models.Role, "")
    self.roles = {}
    for role in response.json.get("roles_collection").get("roles"):
      self.roles[role.get("name")] = role

  def init_users(self):
    """ Create users used by test cases """
    users = [
        ("creator", "Creator"),
        ("notmapped", "Creator"),
        ("mapped", "Creator"),
        ("ProgramReader", "Creator"),
        ("ProgramEditor", "Creator"),
        ("ProgramOwner", "Creator")]
    self.people = {}
    for (name, role) in users:
      _, user = self.object_generator.generate_person(
          data={"name": name}, user_role=role)
      self.people[name] = user

  def delete(self, obj):
    """ Create a delete request for the given object """
    return self.api.delete(obj).status_code

  def get(self, obj):
    """ Create a get request for the given object """
    return self.api.get(obj.__class__, obj.id).status_code

  def put(self, obj):
    """ Create a put request for the given object """
    response = self.api.get(obj.__class__, obj.id)
    if response.status_code == 200:
      return self.api.put(obj, response.json).status_code
    else:
      return response.status_code

  def map(self, dest):
    """ Map src to dest """
    response = self.api.post(all_models.Relationship, {
        "relationship": {"source": {
            "id": self.objects["program"].id,
            "type": self.objects["program"].type,
        }, "destination": {
            "id": dest.id,
            "type": dest.type
        }, "context": None},
    })
    return response.status_code

  def init_objects(self, test_case_name):
    """ Create a Program and a Mapped object for a given test case """
    # Create a program
    test_case = self.test_cases[test_case_name]
    creator = self.people.get('creator')
    self.api.set_user(creator)
    random_title = self.object_generator.random_str()
    response = self.api.post(all_models.Program, {
        "program": {"title": random_title, "context": None},
    })
    self.assertEqual(response.status_code, 201)
    context_id = response.json.get("program").get("context").get("id")
    program_id = response.json.get("program").get("id")
    self.objects["program"] = all_models.Program.query.get(program_id)
    # Create an object:
    for obj in ("mapped_object", "unrelated"):
      random_title = self.object_generator.random_str()
      response = self.api.post(all_models.System, {
          "system": {"title": random_title, "context": None},
      })
      self.assertEqual(response.status_code, 201)
      system_id = response.json.get("system").get("id")
      self.objects[obj] = all_models.System.query.get(system_id)
      # Become the owner
      response = self.api.post(all_models.ObjectOwner, {"object_owner": {
          "person": {
              "id": creator.id,
              "type": "Person",
          }, "ownable": {
              "id": system_id,
              "type": "System"
          }, "context": None}})
    # Map Object to Program
    response = self.api.post(all_models.Relationship, {
        "relationship": {"source": {
            "id": program_id,
            "type": "Program"
        }, "destination": {
            "id": self.objects["mapped_object"].id,
            "type": "System"
        }, "context": None},
    })
    self.assertEqual(response.status_code, 201)

    # Map people to Program:
    if test_case_name != "notmapped":
      person = self.people.get(test_case_name)
      response = self.api.post(all_models.ObjectPerson, {"object_person": {
          "person": {
              "id": person.id,
              "type": "Person",
              "href": "/api/people/{}".format(person.id),
          }, "personable": {
              "type": "Program",
              "href": "/api/programs/{}".format(program_id),
              "id": program_id,
          }, "context": {
              "type": "Context",
              "id": context_id,
              "href": "/api/contexts/{}".format(context_id)
          }}})

    # Add roles to mapped users:
    if "program_role" in test_case:
      person = self.people.get(test_case_name)
      role = self.roles[test_case["program_role"]]
      response = self.api.post(all_models.UserRole, {"user_role": {
          "person": {
              "id": person.id,
              "type": "Person",
              "href": "/api/people/{}".format(person.id),
          }, "role": {
              "type": "Role",
              "href": "/api/roles/{}".format(role["id"]),
              "id": role["id"],
          }, "context": {
              "type": "Context",
              "id": context_id,
              "href": "/api/contexts/{}".format(context_id)
          }}})
      self.assertEqual(response.status_code, 201)

  def test_creator_program_roles(self):
    """ Test creator role with all program scoped roles """
    # Check permissions based on test_cases:
    errors = []
    for test_case in self.test_cases:
      self.init_objects(test_case)
      person = self.people.get(test_case)
      objects = self.test_cases.get(test_case).get('objects')
      self.api.set_user(person)
      for obj in ("unrelated", "mapped_object", "program"):
        actions = objects[obj]
        for action in ("map", "get", "put", "delete"):
          # reset sesion:
          db.session.commit()
          if action not in actions:
            continue
          func = getattr(self, action)
          res = func(self.objects[obj])
          if res != actions[action]:
            errors.append(
                "{}: Tried {} on {}, but received {} instead of {}".format(
                    test_case, action, obj, res, actions[action]))
      # Try mapping
    self.assertEqual(errors, [])

  def test_creator_audit_request_creation(self):
    self.init_objects("ProgramOwner")
    program = self.objects.get("program")
    creator = self.people.get("creator")
    # Create an audit
    response = self.api.post(all_models.Audit, {
        "audit": {
            "title": "Audit for program",
            "status": "Planned",
            "context": {
                "id": program.context_id,
                "type": "Context"
            },
            "program": {
                "context_id": program.context_id,
                "id": program.id,
                "type": "Program",
            },
            "contact": {
                "id": creator.id,
                "type": "Person"
            }
        },
    })
    self.assertEqual(response.status_code, 201)
    audit_id = response.json.get("audit").get("id")
    audit_context_id = response.json.get("audit").get("context").get("id")
    # Create a request
    response = self.api.post(all_models.Request, {
        "request": {
            "title": "Request for audit",
            "status": "In Progress",
            "context": {
                "id": audit_context_id,
                "type": "Context"
            },
            "audit": {
                "id": audit_id,
                "type": "Audit",
            },
            "end_date": "2015-12-08",
            "start_date": "2015-12-01",
            "request_type": "documentation"
        },
    })
    self.assertEqual(response.status_code, 201)
    request_id = response.json.get("request").get("id")

    # Create assignee/requester relationships
    assignee = self.people.get("notmapped")
    response = self.api.post(all_models.Relationship, {
        "relationship": {
            "attrs": {
                "AssigneeType": "Assignee"
            },
            "context": {
                "id": audit_context_id,
                "type": "Context",
            },
            "destination": {
                "id": request_id,
                "type": "Request",
            },
            "source": {
                "id": assignee.id,
                "type": "Person"
            }
        },
    })
    self.assertEqual(response.status_code, 201)
    relationship_id = response.json.get("relationship").get("id")
    response = self.api.get_collection(all_models.Relationship,
                                       relationship_id)
    num = len(response.json["relationships_collection"]["relationships"])
    self.assertEqual(num, 2)
コード例 #14
0
class TestCreatorAudit(TestCase):
    """Set up necessary objects and test Creator role with Audit roles"""
    def setUp(self):
        super(TestCreatorAudit, self).setUp()
        self.generator = Generator()
        self.api = Api()
        self.object_generator = ObjectGenerator()
        self.init_users()
        self.init_roles()
        self.init_test_cases()
        self.objects = {}

    def init_test_cases(self):
        """Create a dict of all possible test cases."""
        self.test_cases = {
            "Auditor": {
                "audit_role": "Auditor",
                "objects": {
                    "audit": {
                        "get": 200,
                        "put": 200,
                        "delete": 403
                    },
                    "mapped_Issue": {
                        "get": 200,
                        "put": 200,
                        "delete": 200
                    },
                    "unrelated_Issue": {
                        "get": 403,
                        "put": 403,
                        "delete": 403,
                        "map": 403,
                    },
                    "mapped_Assessment": {
                        "get": 200,
                        "put": 200,
                        "delete": 200
                    },
                    "unrelated_Assessment": {
                        "get": 403,
                        "put": 403,
                        "delete": 403,
                        "map": 403,
                    }
                }
            },
        }

    def init_roles(self):
        """Create a delete request for the given object."""
        response = self.api.get_query(all_models.Role, "")
        self.roles = {}
        for role in response.json.get("roles_collection").get("roles"):
            self.roles[role.get("name")] = role

    def init_users(self):
        """Create users used by test cases."""
        self.people = {}
        for name in ["creator", "notmapped", "mapped", "Auditor"]:
            _, user = self.object_generator.generate_person(
                data={"name": name}, user_role="Creator")
            self.people[name] = user

        _, user = self.object_generator.generate_person(
            data={"name": "editor"}, user_role="Editor")
        self.people["editor"] = user

    def delete(self, obj):
        """Create a delete request for the given object.

    Args:
        obj (model instance): target object to delete
    Returns:
        int: http response status code
    """
        return self.api.delete(obj).status_code

    def get(self, obj):
        """Create a get request for the given object.

    Args:
        obj (model instance): target object to get
    Returns:
        int: http response status code
    """
        return self.api.get(obj.__class__, obj.id).status_code

    def put(self, obj):
        """Create a put request for the given object.

    Args:
        obj (model instance): target object to put
    Returns:
        int: http response status code
    """
        response = self.api.get(obj.__class__, obj.id)
        if response.status_code == 200:
            return self.api.put(obj, response.json).status_code
        else:
            return response.status_code

    def map(self, dest):
        """Map audit to dest.

    Args:
        dest (model instance): target object to map to the audit
    Returns:
        int: http response status code
    """
        response = self.api.post(
            all_models.Relationship, {
                "relationship": {
                    "source": {
                        "id": self.objects["audit"].id,
                        "type": self.objects["audit"].type,
                    },
                    "destination": {
                        "id": dest.id,
                        "type": dest.type
                    },
                    "context": None
                },
            })
        return response.status_code

    def init_objects(self, test_case_name):
        """Create a Program, an Audit, and a Mapped object for the test case.

    Args:
        test_case_name (string): test case to init for
    """
        # Create a program
        test_case = self.test_cases[test_case_name]
        editor = self.people.get('editor')
        self.api.set_user(editor)
        random_title = factories.random_str()
        response = self.api.post(all_models.Program, {
            "program": {
                "title": random_title,
                "context": None
            },
        })
        self.assertEqual(response.status_code, 201)
        program_id = response.json.get("program").get("id")
        self.objects["program"] = all_models.Program.query.get(program_id)
        response = self.api.post(
            all_models.Audit, {
                "audit": {
                    "title": random_title + " audit",
                    'program': {
                        'id': program_id
                    },
                    "status": "Planned",
                    "context": None
                }
            })
        self.assertEqual(response.status_code, 201)
        context_id = response.json.get("audit").get("context").get("id")
        audit_id = response.json.get("audit").get("id")
        self.objects["audit"] = all_models.Audit.query.get(audit_id)

        for prefix in ("mapped", "unrelated"):
            random_title = factories.random_str()

            response = self.api.post(all_models.Issue, {
                "issue": {
                    "title": random_title,
                    "context": None
                },
            })
            self.assertEqual(response.status_code, 201)
            issue_id = response.json.get("issue").get("id")
            self.objects[prefix +
                         "_Issue"] = all_models.Issue.query.get(issue_id)

            response = self.api.post(all_models.Assessment, {
                "assessment": {
                    "title": random_title,
                    "context": None
                },
            })
            self.assertEqual(response.status_code, 201)
            assessment_id = response.json.get("assessment").get("id")
            self.objects[prefix + "_Assessment"] = \
                all_models.Assessment.query.get(assessment_id)

        self.assertEqual(self.map(self.objects["mapped_Issue"]), 201)
        self.assertEqual(self.map(self.objects["mapped_Assessment"]), 201)

        # Add roles to mapped users:
        if "audit_role" in test_case:
            person = self.people.get(test_case_name)
            role = self.roles[test_case["audit_role"]]
            response = self.api.post(
                all_models.UserRole, {
                    "user_role": {
                        "person": {
                            "id": person.id,
                            "type": "Person",
                            "href": "/api/people/{}".format(person.id),
                        },
                        "role": {
                            "type": "Role",
                            "href": "/api/roles/{}".format(role["id"]),
                            "id": role["id"],
                        },
                        "context": {
                            "type": "Context",
                            "id": context_id,
                            "href": "/api/contexts/{}".format(context_id)
                        }
                    }
                })
            self.assertEqual(response.status_code, 201)

    def test_creator_audit_roles(self):
        """ Test creator role with all audit scoped roles """
        # Check permissions based on test_cases:
        errors = []
        for test_case in self.test_cases:
            self.init_objects(test_case)
            person = self.people.get(test_case)
            objects = self.test_cases.get(test_case).get('objects')
            self.api.set_user(person)
            for obj, actions in objects.iteritems():
                for action in ("map", "get", "put", "delete"):
                    if action not in actions:
                        continue
                    # reset sesion:
                    db.session.commit()
                    func = getattr(self, action)
                    res = func(self.objects[obj])
                    if res != actions[action]:
                        errors.append(
                            "{}: Tried {} on {}, but received {} instead of {}"
                            .format(test_case, action, obj, res,
                                    actions[action]))

        self.assertEqual(errors, [])
コード例 #15
0
ファイル: test_api.py プロジェクト: v-rolich/ggrc-core
class TestReviewApi(TestCase):
  """Base TestCase class proposal api tests."""

  def setUp(self):
    super(TestReviewApi, self).setUp()
    self.api = Api()
    self.api.client.get("/login")
    self.generator = generator.ObjectGenerator()

  def test_simple_get(self):
    """Test simple get"""
    with factories.single_commit():
      control = factories.ControlFactory()
      review = factories.ReviewFactory(
          email_message="test email message",
          notification_type="email",
          reviewable=control,
          status=all_models.Review.STATES.UNREVIEWED,
      )
    resp = self.api.get(all_models.Review, review.id)
    self.assert200(resp)
    self.assertIn("review", resp.json)
    resp_review = resp.json["review"]
    self.assertEqual(all_models.Review.STATES.UNREVIEWED,
                     resp_review["status"])
    self.assertEqual(all_models.Review.NotificationTypes.EMAIL_TYPE,
                     resp_review["notification_type"])
    self.assertEqual("test email message",
                     resp_review["email_message"])

  def test_collection_get(self):
    """Test simple collection get"""
    with factories.single_commit():
      review1 = factories.ReviewFactory(
          status=all_models.Review.STATES.UNREVIEWED
      )
      review2 = factories.ReviewFactory(
          status=all_models.Review.STATES.REVIEWED
      )

    resp = self.api.get_collection(all_models.Review,
                                   [review1.id, review2.id])
    self.assert200(resp)
    self.assertIn("reviews_collection", resp.json)
    self.assertIn("reviews", resp.json["reviews_collection"])
    self.assertEquals(2, len(resp.json["reviews_collection"]["reviews"]))

  def test_create_review(self):
    """Create review via API, check that single relationship is created"""
    control = factories.ControlFactory()
    control_id = control.id
    resp = self.api.post(
        all_models.Review,
        {
            "review": {
                "reviewable": {
                    "type": control.type,
                    "id": control.id,
                },
                "context": None,
                "notification_type": "email",
                "status": all_models.Review.STATES.UNREVIEWED,
                "access_control_list": build_reviewer_acl()
            },
        },
    )
    self.assertEqual(201, resp.status_code)
    review_id = resp.json["review"]["id"]
    review = all_models.Review.query.get(review_id)
    self.assertEqual(all_models.Review.STATES.UNREVIEWED, review.status)
    self.assertEqual(control.type, review.reviewable_type)
    self.assertEqual(control_id, review.reviewable_id)

    control_review_rel_count = all_models.Relationship.query.filter(
        all_models.Relationship.source_id == review.id,
        all_models.Relationship.source_type == review.type,
        all_models.Relationship.destination_id == control_id,
        all_models.Relationship.destination_type == control.type,
    ).union(
        all_models.Relationship.query.filter(
            all_models.Relationship.destination_id == review.id,
            all_models.Relationship.destination_type == review.type,
            all_models.Relationship.source_id == control_id,
            all_models.Relationship.source_type == control.type,
        )
    ).count()
    self.assertEqual(1, control_review_rel_count)

  def test_delete_review(self):
    """Test delete review via API"""
    with factories.single_commit():
      control = factories.ControlFactory()
      control_id = control.id
      review = factories.ReviewFactory(reviewable=control)
      review_id = review.id
    resp = self.api.delete(review)
    self.assert200(resp)
    review = all_models.Review.query.get(review_id)
    control = all_models.Control.query.get(control_id)

    self.assertIsNone(review)
    self.assertEquals(0, len(control.related_objects(_types=["Review"])))

  def test_last_reviewed(self):
    """last_reviewed_by, last_reviewed_by should be set if reviewed"""
    control = factories.ControlFactory()
    resp, review = self.generator.generate_object(
        all_models.Review,
        {
            "reviewable": {
                "type": control.type,
                "id": control.id,
            },
            "context": None,
            "status": all_models.Review.STATES.UNREVIEWED,
            "access_control_list": build_reviewer_acl(),
            "notification_type": all_models.Review.NotificationTypes.EMAIL_TYPE
        },
    )
    review_id = review.id
    resp = self.api.put(
        review,
        {
            "status": all_models.Review.STATES.REVIEWED,
        },
    )
    self.assert200(resp)
    self.assertIsNotNone(resp.json["review"]["last_reviewed_by"])
    self.assertIsNotNone(resp.json["review"]["last_reviewed_at"])

    review = all_models.Review.query.get(review_id)
    self.assertIsNotNone(review.last_reviewed_by)
    self.assertIsNotNone(review.last_reviewed_at)

  def test_reviewable_revisions(self):
    """Check that proper revisions are created"""
    control = factories.ControlFactory()
    resp, review = self.generator.generate_object(
        all_models.Review,
        {
            "reviewable": {
                "type": control.type,
                "id": control.id,
            },
            "context": None,
            "status": all_models.Review.STATES.UNREVIEWED,
            "access_control_list": build_reviewer_acl(),
            "notification_type": all_models.Review.NotificationTypes.EMAIL_TYPE
        },
    )
    control_id = control.id
    reviewable = review.reviewable

    control_revisions = all_models.Revision.query.filter_by(
        resource_id=control_id,
        resource_type=control.type
    ).order_by(
        all_models.Revision.id,
    ).all()
    self.assertEquals(2, len(control_revisions))
    self.assertEquals(all_models.Review.STATES.UNREVIEWED,
                      control_revisions[0].content["review_status"])
    self.assertEquals(all_models.Review.STATES.UNREVIEWED,
                      control_revisions[1].content["review_status"])
    resp = self.api.put(
        review,
        {
            "status": all_models.Review.STATES.REVIEWED,
        },
    )
    self.assert200(resp)

    control_revisions = all_models.Revision.query.filter_by(
        resource_id=control_id,
        resource_type=control.type
    ).order_by(
        all_models.Revision.id,
    ).all()
    self.assertEquals(3, len(control_revisions))
    self.assertEquals(all_models.Review.STATES.REVIEWED,
                      control_revisions[2].content["review_status"])

    resp = self.api.put(
        reviewable,
        {
            "description": "some new description"
        }
    )
    self.assert200(resp)

    control_revisions = all_models.Revision.query.filter_by(
        resource_id=control_id,
        resource_type=control.type
    ).order_by(
        all_models.Revision.id,
    ).all()
    self.assertEquals(4, len(control_revisions))
    self.assertEquals(all_models.Review.STATES.UNREVIEWED,
                      control_revisions[3].content["review_status"])
コード例 #16
0
class TestAuditRBAC(TestCase):
    """Test audit RBAC"""

    CSV_DIR = join(abspath(dirname(__file__)), "test_csvs")

    @classmethod
    def setUpClass(cls):
        """Base setup for entire test suite."""
        TestCase.clear_data()
        cls.response = cls._import_file("audit_rbac.csv")
        cls.people = all_models.Person.eager_query().all()
        cls.audit = all_models.Audit.eager_query().first()
        sources = set(r.source for r in cls.audit.related_sources)
        destinations = set(r.destination
                           for r in cls.audit.related_destinations)
        related = [
            obj for obj in sources.union(destinations)
            if not isinstance(obj, all_models.Person)
        ]
        cls.related_objects = related

    def setUp(self):
        """Imports test_csvs/audit_rbac.csv needed by the tests"""
        self._check_csv_response(self.response, {})
        self.api = Api()
        self.client.get("/login")

    def read(self, objects):
        """Attempt to do a GET request for every object in the objects list"""
        responses = []
        for obj in objects:
            status_code = self.api.get(obj.__class__, obj.id).status_code
            responses.append((obj.type, status_code))
        return responses

    def update(self, objects):
        """Attempt to do a PUT request for every object in the objects list"""
        responses = []
        for obj in objects:
            response = self.api.get(obj.__class__, obj.id)
            status_code = response.status_code
            if response.status_code == 200:
                status_code = self.api.put(obj, response.json).status_code
            responses.append((obj.type, status_code))
        return responses

    def call_api(self, method, expected_statuses):
        """Calls the REST api with a given method and returns a list of
       status_codes that do not match the expected_statuses dict"""
        all_errors = []
        for person in self.people:
            self.api.set_user(person)
            responses = method(self.related_objects + [self.audit])
            for type_, code in responses:
                if code != expected_statuses[person.email]:
                    all_errors.append(
                        "{} does not have {} access to {} ({})".format(
                            person.email, method.__name__, type_, code))
        return all_errors

    def test_read_access_on_mapped(self):
        """Test if people have read access to mapped objects.

    All users except [email protected] should have read access."""
        expected_statuses = defaultdict(lambda: 200)
        for exception in ("*****@*****.**", ):
            expected_statuses[exception] = 403
        errors = self.call_api(self.read, expected_statuses)
        assert not errors, "\n".join(errors)

    def test_update_access_on_mapped(self):
        """Test if people have upate access to mapped objects.

    All users except [email protected], [email protected], [email protected],
    [email protected] should have update access."""
        expected_statuses = defaultdict(lambda: 200)
        for exception in ("*****@*****.**", "*****@*****.**",
                          "*****@*****.**", "*****@*****.**"):
            expected_statuses[exception] = 403
        errors = self.call_api(self.update, expected_statuses)
        assert not errors, "\n".join(errors)
コード例 #17
0
class TestPermissionsOnAssessmentTemplate(TestCase):
    """ Test check permissions for ProgramEditor on

  get and post assessment_temaplte action"""
    @classmethod
    def _get_assessment_template_base(cls, title, audit):
        return {
            "title": title,
            "_NON_RELEVANT_OBJ_TYPES": {},
            "_objectTypes": {},
            "audit": {
                "id": audit.id
            },
            "audit_title": audit.title,
            "people_value": [],
            "default_people": {
                "assignees": "Admin",
                "verifiers": "Admin",
            },
            "context": {
                "id": audit.context.id
            },
        }

    def setUp(self):
        super(TestPermissionsOnAssessmentTemplate, self).setUp()
        self.api = Api()
        editor = all_models.AccessControlRole.query.filter(
            all_models.AccessControlRole.name == "Program Editors").one()
        self.generator = ObjectGenerator()
        _, self.editor = self.generator.generate_person(user_role="Creator")
        _, program = self.generator.generate_object(
            all_models.Program, {
                "access_control_list":
                [acl_helper.get_acl_json(editor.id, self.editor.id)]
            })
        program_id = program.id
        _, audit = self.generator.generate_object(
            all_models.Audit,
            {
                "title": "Assessment Template test Audit",
                "program": {
                    "id": program_id
                },
                "status": "Planned"
            },
        )
        audit_id = audit.id

        generated_at = self.generator.generate_object(
            all_models.AssessmentTemplate,
            self._get_assessment_template_base("Template", audit))
        self.assessment_template_resp, assessment_template = generated_at
        assessment_template_id = assessment_template.id
        self.api.set_user(self.editor)
        self.perms_data = self.api.client.get("/permissions").json
        self.audit = all_models.Audit.query.get(audit_id)
        self.assessment_template = all_models.AssessmentTemplate.query.get(
            assessment_template_id)

    def test_post_action(self):
        """Test create action on AssessmentTemplate created by api"""
        data = [{
            "assessment_template":
            self._get_assessment_template_base("123", self.audit)
        }]
        self.api.set_user(self.editor)
        resp = self.api.post(all_models.AssessmentTemplate, data)
        self.assert200(resp)

    def test_get_action(self):
        """Test read action on AssessmentTemplate created by api"""
        resp = self.api.get(all_models.AssessmentTemplate,
                            self.assessment_template.id)
        self.assert200(resp)

    def test_put_action(self):
        """Test update action on AssessmentTemplate created by api"""
        to_update = copy.deepcopy(self.assessment_template_resp.json)
        new_title = "new_{}".format(self.assessment_template.title)
        to_update['assessment_template']['title'] = new_title
        resp = self.api.put(self.assessment_template, to_update)
        self.assert200(resp)
        assessment_tmpl = all_models.AssessmentTemplate.query.get(
            self.assessment_template.id)
        self.assertEqual(new_title, assessment_tmpl.title)

    def test_delete_action(self):
        """Test delete action on AssessmentTemplate created by api"""
        resp = self.api.delete(self.assessment_template)
        self.assert200(resp)
        self.assertFalse(
            all_models.AssessmentTemplate.query.filter(
                all_models.AssessmentTemplate ==
                self.assessment_template.id).all())
コード例 #18
0
class TestPermissions(TestCase):
  """Test checks permissions for proposals."""

  def setUp(self):
    super(TestPermissions, self).setUp()
    self.api = Api()
    roles = {r.name: r for r in all_models.Role.query.all()}
    factories.AccessControlRoleFactory(
        name="ACL_Reader",
        object_type="Risk",
        update=0
    )
    factories.AccessControlRoleFactory(
        name="ACL_Editor",
        object_type="Risk"
    )
    factories.AccessControlRoleFactory(
        name="ACL_Nobody",
        object_type="Risk",
        read=0,
        update=0,
        delete=0,
    )
    with factories.single_commit():
      self.risk = factories.RiskFactory()
      self.program = factories.ProgramFactory()
      self.program.context.related_object = self.program
      self.relationship = factories.RelationshipFactory(
          source=self.program,
          destination=self.risk,
          context=self.program.context,
      )
      self.people = {
          "Creator": factories.PersonFactory(),
          "Reader": factories.PersonFactory(),
          "Editor": factories.PersonFactory(),
          "Administrator": factories.PersonFactory(),
          "ACL_Reader": factories.PersonFactory(),
          "ACL_Editor": factories.PersonFactory(),
          "ACL_Nobody": factories.PersonFactory(),
          "Program Editors": factories.PersonFactory(),
          "Program Managers": factories.PersonFactory(),
          "Program Readers": factories.PersonFactory(),
      }
      for role_name in ["Creator", "Reader", "Editor", "Administrator"]:
        rbac_factories.UserRoleFactory(role=roles[role_name],
                                       person=self.people[role_name])
      for role_name in ["Program Editors",
                        "Program Managers",
                        "Program Readers"]:
        person = self.people[role_name]
        rbac_factories.UserRoleFactory(role=roles["Creator"], person=person)
        factories.AccessControlPersonFactory(
            ac_list=self.program.acr_name_acl_map[role_name],
            person=person,
        )
      self.proposal = factories.ProposalFactory(
          instance=self.risk,
          content={
              "access_control_list": {},
              "custom_attribute_values": {},
              "fields": {},
              "mapping_fields": {},
              "mapping_list_fields": {},
          }
      )
      factories.RelationshipFactory(
          source=self.risk,
          destination=self.proposal,
      )

      for role_name in ["ACL_Reader", "ACL_Editor", "ACL_Nobody"]:
        person = self.people[role_name]
        rbac_factories.UserRoleFactory(role=roles["Creator"], person=person)
        factories.AccessControlPersonFactory(
            ac_list=self.risk.acr_name_acl_map[role_name],
            person=person,
        )

  @ddt.data(
      ("Creator", 403),
      ("Reader", 200),
      ("Editor", 200),
      ("ACL_Reader", 200),
      ("ACL_Editor", 200),
      ("ACL_Nobody", 403),
      ("Administrator", 200),
      ("Program Editors", 200),
      ("Program Managers", 200),
      ("Program Readers", 200),
  )
  @ddt.unpack
  def test_permissions_on_get(self, role_name, status):
    """Test get proposals for {0}."""
    proposal_id = self.proposal.id
    self.api.set_user(self.people[role_name])
    self.client.get("/login")
    resp = self.api.get(all_models.Proposal, proposal_id)
    self.assertEqual(status, resp.status_code)

  def api_proposal_status_change(self, proposal_id, status):
    return self.api.put(all_models.Proposal.query.get(proposal_id),
                        {"status": status})

  @ddt.data(
      ("Creator", 403),
      ("Reader", 403),
      ("Editor", 200),
      ("Administrator", 200),
      ("ACL_Reader", 403),
      ("ACL_Editor", 200),
      ("ACL_Nobody", 403),
      ("Program Editors", 200),
      ("Program Managers", 200),
      ("Program Readers", 403)
  )
  @ddt.unpack
  def test_permissions_on_apply(self, role_name, status):
    """Test apply proposals for {0}."""
    proposal_id = self.proposal.id
    self.api.set_user(self.people[role_name])
    self.client.get("/login")
    resp = self.api_proposal_status_change(proposal_id,
                                           all_models.Proposal.STATES.APPLIED)
    self.assertEqual(status, resp.status_code)

  @ddt.data(
      ("Creator", 403),
      ("Reader", 403),
      ("Editor", 200),
      ("ACL_Reader", 403),
      ("ACL_Editor", 200),
      ("ACL_Nobody", 403),
      ("Administrator", 200),
      ("Program Editors", 200),
      ("Program Managers", 200),
      ("Program Readers", 403),
  )
  @ddt.unpack
  def test_permissions_on_decline(self, role_name, status):
    """Test decline proposals for {0}."""
    proposal_id = self.proposal.id
    self.api.set_user(self.people[role_name])
    self.client.get("/login")
    resp = self.api_proposal_status_change(proposal_id,
                                           all_models.Proposal.STATES.DECLINED)
    self.assertEqual(status, resp.status_code)

  @ddt.data(
      ("Creator", 403),
      ("Reader", 201),
      ("Editor", 201),
      ("ACL_Reader", 201),
      ("ACL_Editor", 201),
      ("ACL_Nobody", 403),
      ("Administrator", 201),
      ("Program Editors", 201),
      ("Program Managers", 201),
      ("Program Readers", 201),
  )
  @ddt.unpack
  def test_permissions_on_create(self, role_name, status):
    """Test create proposal for {0}."""
    data = {
        "proposal": {
            "instance": {
                "id": self.risk.id,
                "type": self.risk.type,
            },
            "full_instance_content": {"title": "new_title"},
            "agenda": "update cav",
            "context": None,
        }
    }
    self.api.set_user(self.people[role_name])
    self.client.get("/login")
    resp = self.api.post(all_models.Proposal, data)
    self.assertEqual(status, resp.status_code)

  @ddt.data(
      ("Creator", 0),
      ("Reader", 1),
      ("Editor", 1),
      # Following two tests have been commented out as the functionality for
      # custom role propagation has been temporarily removed This test should
      # be enabled back in scope of ticket GGRC-4991
      # ("ACL_Reader", 1),
      # ("ACL_Editor", 1),
      ("ACL_Nobody", 0),
      ("Administrator", 1),
      ("Program Editors", 1),
      ("Program Managers", 1),
      ("Program Readers", 1),
  )
  @ddt.unpack
  def test_query_filter(self, role_name, expected_count):
    """Test query proposals for {0}.

    Args:
        role_name: string, unique key,
                   shows the position of user in generated infrustructure
        expected_count: int, number of proposals,
                        that should be filtered by query
    """
    risk_id = self.risk.id
    data = [{
        "limit": [0, 5],
        "object_name": all_models.Proposal.__name__,
        "order_by":[
            {"name": "status", "desc": True},
            {"name": "created_at", "desc": True},
        ],
        "filters": {
            "expression": {
                "left": {
                    "left": "instance_type",
                    "op": {"name": "="},
                    "right": self.risk.type,
                },
                "op": {"name": "AND"},
                "right": {
                    "left": "instance_id",
                    "op": {"name": "="},
                    "right": risk_id,
                },
            },
        },
    }]
    self.api.set_user(self.people[role_name])
    self.client.get("/login")
    headers = {"Content-Type": "application/json", }
    resp = self.api.client.post("/query",
                                data=json.dumps(data),
                                headers=headers).json
    self.assertEqual(1, len(resp))
    self.assertEqual(expected_count, resp[0]["Proposal"]["count"])
コード例 #19
0
class TestAccessControlList(TestCase):
  """TestAccessControlList"""

  def setUp(self):
    super(TestAccessControlList, self).setUp()
    self.api = Api()
    self.person = factories.PersonFactory(name="My Person")
    self.control = factories.ControlFactory()
    self.acr = factories.AccessControlRoleFactory(
        object_type="Control",
        read=True
    )
    self.second_acr = factories.AccessControlRoleFactory(
        object_type="Control",
        read=True
    )
    self.acl = factories.AccessControlListFactory(
        object=self.control,
        ac_role_id=self.acr.id,
        person=self.person
    )

  def _post_control(self, id_, person_id, collection=False):
    """Helper function for posting a control"""
    title = random_str(prefix="Control - ")
    control = {
        "control": {
            "title": title,
            "type": "Control",
            "context": None,
            "access_control_list": [
                _acl_json(id_, person_id)
            ]
        },
    }
    response = self.api.post(
        all_models.Control, [control] if collection else control)
    assert response.status_code == 200 or response.status_code == 201, \
        "Control with acl not created successfully {}".format(response.status)

    if collection:
      return response.json[0][1]
    return response.json

  def test_object_roles(self):
    """Test if roles are fetched with the object"""
    id_, person_id = self.acr.id, self.person.id
    response = self.api.get(all_models.Control, self.control.id)
    assert response.status_code == 200, \
        "Failed to fetch created control {}".format(response.status)

    assert "access_control_list" in response.json["control"], \
        "Access Control List not a property in {}".format(
            response.json["control"].keys())

    ac_list = response.json["control"]["access_control_list"]
    assert len(ac_list) == 1, "{}".format(len(ac_list))

    assert ac_list[0]["ac_role_id"] == id_, \
        "ac_role_id not properly set {}".format(ac_list[0].get("ac_role_id"))
    assert ac_list[0]["person"]["id"] == person_id, \
        "Person stub not properly set {}".format(ac_list[0]["person"])

  def test_post_object_roles(self):
    """Test if roles are stored correctly when POSTed with the object"""
    id_, person_id = self.acr.id, self.person.id
    response = self._post_control(id_, person_id)

    acl = response["control"]["access_control_list"]
    _acl_asserts(acl, id_, person_id)

  def test_acl_revision_content(self):
    """Test if the access control list is added to revisions"""
    id_, person_id = self.acr.id, self.person.id
    response = self._post_control(id_, person_id)
    control_id = response["control"]["id"]
    rev = all_models.Revision.query.filter(
        all_models.Revision.resource_id == control_id,
        all_models.Revision.resource_type == "Control"
    ).first()

    acl = rev.content["access_control_list"]
    _acl_asserts(acl, id_, person_id)

  def test_put_object_roles(self):
    """Test if PUTing object roles saves them correctly"""
    id_2, person_id = self.second_acr.id, self.person.id

    response = self.api.get(all_models.Control, self.control.id)
    assert response.status_code == 200, \
        "Failed to fetch created control {}".format(response.status)
    control = response.json['control']
    control['access_control_list'].append(_acl_json(id_2, person_id))
    response = self.api.put(self.control, {"control": control})
    assert response.status_code == 200, \
        "PUTing control failed {}".format(response.status)
    acl = response.json['control']['access_control_list']
    assert len(acl) == 2, \
        "Access control list not correctly updated {}".format(acl)

  def test_put_removing_roles(self):
    """Test if PUTing an empty list removes object roles correct"""
    response = self.api.get(all_models.Control, self.control.id)
    assert response.status_code == 200, \
        "Failed to fetch created control {}".format(response.status)
    control = response.json['control']
    control['access_control_list'] = []
    response = self.api.put(self.control, {"control": control})
    assert response.status_code == 200, \
        "PUTing control failed {}".format(response.status)
    acl = response.json['control']['access_control_list']
    assert len(acl) == 0, \
        "Access control list not empty {}".format(acl)

  def test_acl_indexing_on_post(self):
    """Test if roles are stored correctly when POSTed with the object"""
    id_, person_id = self.acr.id, self.person.id
    response = self._post_control(id_, person_id, True)
    control = response["control"]
    res = mysql.MysqlRecordProperty.query.filter(
        mysql.MysqlRecordProperty.type == "Control",
        mysql.MysqlRecordProperty.key == control["id"],
        mysql.MysqlRecordProperty.property == self.acr.name
    ).all()
    assert len(res) > 0, \
        "Full text record index not created for {}".format(self.acr.name)
    # email is presented in __sort__ subproperty as well
    assert len([r for r in res if r.content == self.person.email]) == 2, \
        "Person email not indexed {}".format(self.person.email)
    assert len([r for r in res if r.content == self.person.name]) == 1, \
        "Person name not indexed {}".format(self.person.name)

  def test_acl_revision_count(self):
    """Test if acl revision is created when object POSTed and PUTed"""
    id_, person_id = self.acr.id, self.person.id

    response = self._post_control(id_, person_id)
    # One ACL and Control created in setUp and on by POST
    self.assertEqual(
        all_models.Revision.query.filter_by(
            resource_type="AccessControlList"
        ).count(),
        2
    )
    self.assertEqual(
        all_models.Revision.query.filter_by(
            resource_type="Control"
        ).count(),
        2
    )

    # If content of "access_control_list" is changed,
    # new revision should be created for ACL
    control = response["control"]
    control["access_control_list"] = []
    self.api.put(
        all_models.Control.query.get(control["id"]),
        {"control": control}
    )
    self.assertEqual(
        all_models.Revision.query.filter_by(
            resource_type="AccessControlList"
        ).count(),
        3
    )
    self.assertEqual(
        all_models.Revision.query.filter_by(
            resource_type="Control"
        ).count(),
        3
    )
コード例 #20
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"])
コード例 #21
0
ファイル: test_creator.py プロジェクト: zidarsk8/ggrc-core
class TestCreator(TestCase):
  """ TestCreator """

  def setUp(self):
    super(TestCreator, self).setUp()
    self.generator = Generator()
    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):
    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"])
    audit_id = factories.AuditFactory().id
    all_errors = []
    base_models = set([
        "Control", "DataAsset", "Contract",
        "Policy", "Regulation", "Standard", "Document", "Facility",
        "Market", "Objective", "OrgGroup", "Vendor", "Product",
        "Clause", "System", "Process", "Project", "AccessGroup"
    ])
    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.api.post(model, {
            table_singular: {
                "title": model_singular,
                "context": None,
                "reference_url": "ref",
                "contact": {
                    "type": "Person",
                    "id": self.users["creator"].id,
                },
                "audit": {  # this is ignored on everything but Issues
                    "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 len(collection) != 0:
          all_errors.append(
              "{} can retrieve object if not owner (collection)"
              .format(model_singular))
          continue
        # Become an owner
        response = self.api.post(all_models.ObjectOwner, {"object_owner": {
            "person": {
                "id": self.users['creator'].id,
                "type": "Person",
            }, "ownable": {
                "type": model_singular,
                "id": obj_id
            }, "context": None}})
        if response.status_code != 201:
          all_errors.append("{} can't create owner {}.".format(
              model_singular, response.status))
          continue

        # 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 len(collection) == 0:
          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'])
    response = self.api.post(all_models.Policy, {
        "policy": {"title": "Creator Policy", "context": None},
    })
    obj_id = response.json.get("policy").get("id")
    self.api.post(all_models.ObjectOwner, {"object_owner": {
        "person": {
            "id": self.users['creator'].id,
            "type": "Person",
        }, "ownable": {
            "type": "Policy",
            "id": obj_id,
        }, "context": None}})
    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_creator_cannot_be_owner(self):
    """Test if creator cannot become owner of the object he has not created"""
    self.api.set_user(self.users['admin'])
    _, obj = self.generator.generate(all_models.Regulation, "regulation", {
        "regulation": {"title": "Test regulation", "context": None},
    })
    self.api.set_user(self.users['creator'])
    response = self.api.post(all_models.ObjectOwner, {"object_owner": {
        "person": {
            "id": self.users['creator'].id,
            "type": "Person",
        }, "ownable": {
            "type": "Regulation",
            "id": obj.id,
        }, "context": None}})
    self.assertEqual(response.status_code, 403)

  def test_relationships_access(self):
    """Check if creator cannot access relationship objects"""
    self.api.set_user(self.users['admin'])
    _, obj_0 = self.generator.generate(all_models.Regulation, "regulation", {
        "regulation": {"title": "Test regulation", "context": None},
    })
    _, obj_1 = self.generator.generate(all_models.Regulation, "regulation", {
        "regulation": {"title": "Test regulation 2", "context": None},
    })
    response, rel = self.generator.generate(
        all_models.Relationship, "relationship", {
            "relationship": {"source": {
                "id": obj_0.id,
                "type": "Regulation"
            }, "destination": {
                "id": obj_1.id,
                "type": "Regulation"
            }, "context": None},
        }
    )
    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):
      return self.generator.generate(all_models.Section, "section", {
          "section": {"title": title, "context": None},
      })[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 Section 1")
    obj_2 = gen("Test Section 2")

    self.api.post(all_models.ObjectOwner, {"object_owner": {
        "person": {
            "id": self.users['creator'].id,
            "type": "Person",
        }, "ownable": {
            "type": "Section",
            "id": obj_2.id,
        }, "context": None}})

    self.api.set_user(self.users["creator"])
    check(obj_1, 0)
    check(obj_2, 2)
コード例 #22
0
class TestReader(TestCase):
    """ Test reader role """
    def setUp(self):
        super(TestReader, self).setUp()
        self.generator = Generator()
        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")]
        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):
        return
        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):
        return
        """ Test Basic create/read,update/delete operations """
        self.api.set_user(self.users["reader"])
        all_errors = []
        base_models = set([
            "Control", "Assessment", "DataAsset", "Contract", "Policy",
            "Regulation", "Standard", "Document", "Facility", "Market",
            "Objective", "OrgGroup", "Vendor", "Product", "Clause", "System",
            "Process", "Issue", "Project", "AccessGroup", "Request"
        ])
        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.api.post(
                    model, {
                        table_singular: {
                            "title": model_singular,
                            "context": None,
                            "reference_url": "ref",
                            "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 len(collection) == 0:
                    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):
        return
        """ 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
            },
        })
        obj_id = response.json.get("policy").get("id")
        self.api.post(
            all_models.ObjectOwner, {
                "object_owner": {
                    "person": {
                        "id": self.users['reader'].id,
                        "type": "Person",
                    },
                    "ownable": {
                        "type": "Policy",
                        "id": obj_id,
                    },
                    "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_reader_cannot_be_owner(self):
        """ Test if reader cannot become owner of the object he has not created """
        self.api.set_user(self.users['admin'])
        _, obj = self.generator.generate(all_models.Regulation, "regulation", {
            "regulation": {
                "title": "Test regulation",
                "context": None
            },
        })
        self.api.set_user(self.users['reader'])
        response = self.api.post(
            all_models.ObjectOwner, {
                "object_owner": {
                    "person": {
                        "id": self.users['reader'].id,
                        "type": "Person",
                    },
                    "ownable": {
                        "type": "Regulation",
                        "id": obj.id,
                    },
                    "context": None
                }
            })
        self.assertEqual(response.status_code, 403)

    def test_relationships_access(self):
        """Check if reader can access relationship objects"""
        self.api.set_user(self.users['admin'])
        _, obj_0 = self.generator.generate(all_models.Regulation, "regulation",
                                           {
                                               "regulation": {
                                                   "title": "Test regulation",
                                                   "context": None
                                               },
                                           })
        _, obj_1 = self.generator.generate(
            all_models.Regulation, "regulation", {
                "regulation": {
                    "title": "Test regulation 2",
                    "context": None
                },
            })
        response, rel = self.generator.generate(
            all_models.Relationship, "relationship", {
                "relationship": {
                    "source": {
                        "id": obj_0.id,
                        "type": "Regulation"
                    },
                    "destination": {
                        "id": obj_1.id,
                        "type": "Regulation"
                    },
                    "context": None
                },
            })
        relationship_id = rel.id
        self.assertEqual(response.status_code, 201)
        self.api.set_user(self.users['reader'])
        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, 1)

    def test_creation_of_mappings(self):
        self.generator.api.set_user(self.users["admin"])
        _, control = self.generator.generate(all_models.Control, "control", {
            "control": {
                "title": "Test Control",
                "context": None
            },
        })
        self.generator.api.set_user(self.users['reader'])
        _, program = self.generator.generate(all_models.Program, "program", {
            "program": {
                "title": "Test Program",
                "context": None
            },
        })

        response, _ = self.generator.generate(
            all_models.Relationship, "relationship", {
                "relationship": {
                    "destination": {
                        "id": program.id,
                        "type": "Program"
                    },
                    "source": {
                        "id": control.id,
                        "type": "Control"
                    },
                    "context": {
                        "id": program.context.id,
                        "type": "context"
                    }
                },
            })
        self.assertEqual(response.status_code, 403)
コード例 #23
0
class TestCreatorProgram(TestCase):
    """Set up necessary objects and test Creator role with Program roles"""
    def setUp(self):
        super(TestCreatorProgram, self).setUp()
        self.generator = Generator()
        self.api = Api()
        self.object_generator = ObjectGenerator()
        self.init_users()
        self.init_roles()
        self.init_test_cases()
        self.objects = {}

    def init_test_cases(self):
        """ Create a dict of all possible test cases """
        self.test_cases = {
            "notmapped": {
                "objects": {
                    "program": {
                        "get": 403,
                        "put": 403,
                        "delete": 403
                    },
                    "mapped_object": {
                        "get": 403,
                        "put": 403,
                        "delete": 403
                    },
                    "unrelated": {
                        "get": 403,
                        "put": 403,
                        "delete": 403,
                        "map": 403,
                    }
                },
            },
            "mapped": {
                "objects": {
                    "program": {
                        "get": 403,
                        "put": 403,
                        "delete": 403
                    },
                    "mapped_object": {
                        "get": 403,
                        "put": 403,
                        "delete": 403
                    },
                    "unrelated": {
                        "get": 403,
                        "put": 403,
                        "delete": 403,
                        "map": 403,
                    }
                }
            },
            "ProgramReader": {
                "program_role": "Program Readers",
                "objects": {
                    "program": {
                        "get": 200,
                        "put": 403,
                        "delete": 403
                    },
                    "mapped_object": {
                        "get": 200,
                        "put": 403,
                        "delete": 403
                    },
                    "unrelated": {
                        "get": 403,
                        "put": 403,
                        "delete": 403,
                        "map": 403,
                    }
                }
            },
            "ProgramManager": {
                "program_role": "Program Managers",
                "objects": {
                    "program": {
                        "get": 200,
                        "put": 200,
                        "delete": 200
                    },
                    "mapped_object": {
                        "get": 200,
                        "put": 200,
                        "delete": 200,
                    },
                    "unrelated": {
                        "get": 403,
                        "put": 403,
                        "delete": 403,
                        "map": 403,
                    }
                }
            },
            "ProgramEditor": {
                "program_role": "Program Editors",
                "objects": {
                    "program": {
                        "get": 200,
                        "put": 200,
                        "delete": 200
                    },
                    "mapped_object": {
                        "get": 200,
                        "put": 200,
                        "delete": 200
                    },
                    "unrelated": {
                        "get": 403,
                        "put": 403,
                        "delete": 403,
                        "map": 403,
                    }
                }
            },
        }

    def init_roles(self):
        """ Create a delete request for the given object """
        ac_roles = all_models.AccessControlRole.query.all()
        self.ac_roles = {}
        for ac_role in ac_roles:
            self.ac_roles[ac_role.name] = ac_role.id

    def init_users(self):
        """ Create users used by test cases """
        users = [("creator", "Creator"), ("notmapped", "Creator"),
                 ("mapped", "Creator"), ("ProgramReader", "Creator"),
                 ("ProgramEditor", "Creator"), ("ProgramManager", "Creator")]
        self.people = {}
        for (name, role) in users:
            _, user = self.object_generator.generate_person(data={
                "name":
                name,
                "email":
                name + "@example.com"
            },
                                                            user_role=role)
            self.people[name] = user

    def delete(self, obj):
        """ Create a delete request for the given object """
        return self.api.delete(obj).status_code

    def get(self, obj):
        """ Create a get request for the given object """
        return self.api.get(obj.__class__, obj.id).status_code

    def put(self, obj):
        """ Create a put request for the given object """
        response = self.api.get(obj.__class__, obj.id)
        if response.status_code == 200:
            return self.api.put(obj, response.json).status_code
        else:
            return response.status_code

    def map(self, dest):
        """ Map src to dest """
        response = self.api.post(
            all_models.Relationship, {
                "relationship": {
                    "source": {
                        "id": self.objects["program"].id,
                        "type": self.objects["program"].type,
                    },
                    "destination": {
                        "id": dest.id,
                        "type": dest.type
                    },
                    "context": None
                },
            })
        return response.status_code

    def init_objects(self, test_case_name):
        """ Create a Program and a Mapped object for a given test case """
        # Create a program
        test_case = self.test_cases[test_case_name]
        creator = self.people.get('creator')
        self.api.set_user(creator)
        random_title = factories.random_str()
        person = self.people.get(test_case_name)
        acl = [
            acl_helper.get_acl_json(self.ac_roles["Program Managers"],
                                    creator.id)
        ]
        if "program_role" in test_case:
            ac_role_id = self.ac_roles[test_case["program_role"]]
            acl.append(acl_helper.get_acl_json(ac_role_id, person.id))
        response = self.api.post(
            all_models.Program, {
                "program": {
                    "title": random_title,
                    "context": None,
                    "access_control_list": acl
                },
            })
        self.assertEqual(response.status_code, 201,
                         "Creator can't create program")
        context_id = response.json.get("program").get("context").get("id")
        program_id = response.json.get("program").get("id")

        # Use admin owner role to map it with system
        acr_id = all_models.AccessControlRole.query.filter_by(
            object_type="System", name="Admin").first().id
        self.objects["program"] = all_models.Program.query.get(program_id)

        # Create an object:
        for obj in ("mapped_object", "unrelated"):
            random_title = factories.random_str()
            response = self.api.post(
                all_models.System, {
                    "system": {
                        "title":
                        random_title,
                        "context":
                        None,
                        "access_control_list":
                        [acl_helper.get_acl_json(acr_id, creator.id)],
                    },
                })
            self.assertEqual(response.status_code, 201,
                             "Creator can't create object")
            system_id = response.json.get("system").get("id")
            self.objects[obj] = all_models.System.query.get(system_id)

        # Map Object to Program
        response = self.api.post(
            all_models.Relationship, {
                "relationship": {
                    "source": {
                        "id": program_id,
                        "type": "Program"
                    },
                    "destination": {
                        "id": self.objects["mapped_object"].id,
                        "type": "System"
                    },
                    "context": None
                },
            })
        self.assertEqual(response.status_code, 201,
                         "Creator can't map object to program")

        # Map people to Program:
        if test_case_name != "notmapped":
            person = self.people.get(test_case_name)
            response = self.api.post(
                all_models.ObjectPerson, {
                    "object_person": {
                        "person": {
                            "id": person.id,
                            "type": "Person",
                            "href": "/api/people/{}".format(person.id),
                        },
                        "personable": {
                            "type": "Program",
                            "href": "/api/programs/{}".format(program_id),
                            "id": program_id,
                        },
                        "context": {
                            "type": "Context",
                            "id": context_id,
                            "href": "/api/contexts/{}".format(context_id)
                        }
                    }
                })

    def test_creator_program_roles(self):
        """ Test creator role with all program scoped roles """
        # Check permissions based on test_cases:
        errors = []
        for test_case in self.test_cases:
            self.init_objects(test_case)
            person = self.people.get(test_case)
            objects = self.test_cases.get(test_case).get('objects')
            self.api.set_user(person)
            for obj in ("unrelated", "mapped_object", "program"):
                actions = objects[obj]
                for action in ("map", "get", "put", "delete"):
                    # reset sesion:
                    db.session.commit()
                    if action not in actions:
                        continue
                    func = getattr(self, action)
                    res = func(self.objects[obj])
                    if res != actions[action]:
                        errors.append(
                            "{}: Tried {} on {}, but received {} instead of {}"
                            .format(test_case, action, obj, res,
                                    actions[action]))
            # Try mapping
        self.assertEqual(errors, [])
コード例 #24
0
class TestReader(TestCase):
    """Test Assignable RBAC"""
    def setUp(self):
        super(TestReader, self).setUp()
        self.generator = Generator()
        self.api = Api()
        self.object_generator = ObjectGenerator()
        self.init_users()
        self.init_assignable()

    def init_users(self):
        """ Init users needed by the test cases """
        users = [("creator", "Creator"), ("reader", "Reader"),
                 ("editor", "Editor"), ("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 init_assignable(self):
        """Creates the assignable object used by all the tests"""
        self.api.set_user(self.users["editor"])
        response = self.api.post(
            all_models.Assessment,
            {"assessment": {
                "title": "Assessment",
                "context": None,
            }})
        obj_id = response.json.get("assessment").get("id")
        self.assertEqual(response.status_code, 201,
                         "Error setting up Assessment")
        self.obj_json = response.json
        self.obj = all_models.Assessment.query.get(obj_id)

    def _post_relationship(self, user, obj_id):
        """Helper method for creating assignees on an object"""
        return self.api.post(
            all_models.Relationship, {
                "relationship": {
                    "source": {
                        "id": obj_id,
                        "type": "Assessment"
                    },
                    "destination": {
                        "id": user.id,
                        "type": "Person"
                    },
                    "attrs": {
                        "AssigneeType": "Creator"
                    },
                    "context": None
                },
            })

    def test_basic_operations_with_no_assignee(self):
        """Editor creates an Assessment, but doesn't assign Reader/Creator as
       assignee. Reader should have Read access, Creator should have no access
    """

        # Reader should have read access, but shouldn't be allowed to edit or
        # create another assingee
        self.api.set_user(self.users["reader"])
        response = self.api.get(all_models.Assessment, self.obj.id)
        self.assertEqual(response.status_code, 200)
        response = self.api.put(self.obj, self.obj_json)
        self.assertEqual(response.status_code, 403)
        response = self._post_relationship(self.users["reader"], self.obj.id)
        self.assertEqual(response.status_code, 403)

        # Creator should have no access. We skip the put request because we can't
        # get the object etag.
        self.api.set_user(self.users["creator"])
        response = self.api.get(all_models.Assessment, self.obj.id)
        self.assertEqual(response.status_code, 403)
        response = self._post_relationship(self.users["reader"], self.obj.id)
        self.assertEqual(response.status_code, 403)

    def test_basic_operations_with_assignee(self):
        """Test if Reader/Creator have CRUD access once they become assignees"""

        # Admin adds reader as an assignee
        self.api.set_user(self.users["admin"])
        response = self._post_relationship(self.users["reader"], self.obj.id)
        self.assertEqual(response.status_code, 201)

        # Reader is now allowed to update the object
        self.api.set_user(self.users["reader"])
        response = self.api.get(all_models.Assessment, self.obj.id)
        self.assertEqual(response.status_code, 200)
        response = self.api.put(self.obj, response.json)
        self.assertEqual(response.status_code, 200)

        # Reader adds creator as an assignee
        response = self._post_relationship(self.users["creator"], self.obj.id)
        self.assertEqual(response.status_code, 201)

        # Creator now has CRUD access
        self.api.set_user(self.users["creator"])
        response = self.api.get(all_models.Assessment, self.obj.id)
        self.assertEqual(response.status_code, 200)
        response = self.api.put(self.obj, response.json)

        # Creator should even be allowed to add new assignees
        response = self._post_relationship(self.users["admin"], self.obj.id)
        self.assertEqual(response.status_code, 201)

    def test_readability_of_mapped_objects(self):
        """Test if assignees get Read access on all mapped objects"""

        # Editor creates a System object and maps it to the assignable object
        self.api.set_user(self.users["editor"])
        response = self.api.post(
            all_models.System,
            {"system": {
                "title": "System",
                "context": None,
            }})
        system_id = response.json.get("system").get("id")
        system = all_models.System.query.get(system_id)
        self.api.post(
            all_models.Relationship, {
                "relationship": {
                    "source": {
                        "id": self.obj.id,
                        "type": "Assessment"
                    },
                    "destination": {
                        "id": system_id,
                        "type": "System"
                    },
                    "context": None
                },
            })

        # Since creator is not an assignee she should not have access to any of the
        # two objects
        self.api.set_user(self.users["creator"])
        response = self.api.get(all_models.Assessment, self.obj.id)
        self.assertEqual(response.status_code, 403)
        response = self.api.get(all_models.System, system_id)
        self.assertEqual(response.status_code, 403)

        # Editor adds creator as an assignee
        self.api.set_user(self.users["editor"])
        response = self._post_relationship(self.users["creator"], self.obj.id)

        # Creator should now have read access on the mapped object
        self.api.set_user(self.users["creator"])
        response = self.api.get(all_models.System, system_id)
        self.assertEqual(response.status_code, 200)

        # But he should still not be allowed to update
        response = self.api.put(system, response.json)
        self.assertEqual(response.status_code, 403)
コード例 #25
0
class TestCreator(TestCase):
  """ TestCreator """

  def setUp(self):
    super(TestCreator, self).setUp()
    self.generator = Generator()
    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 = set([
        "Control", "DataAsset", "Contract",
        "Policy", "Regulation", "Standard", "Document", "Facility",
        "Market", "Objective", "OrgGroup", "Vendor", "Product",
        "Clause", "System", "Process", "Project", "AccessGroup",
        "Metric"
    ])
    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.api.post(model, {
            table_singular: {
                "title": model_singular,
                "context": None,
                "documents_reference_url": "ref",
                "link": "https://example.com",  # ignored except for Document
                "contact": {
                    "type": "Person",
                    "id": creator_id,
                },
                "audit": {  # this is ignored on everything but Issues
                    "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"
        ).first()
        factories.AccessControlListFactory(
            object_id=obj_id,
            object_type=model_singular,
            ac_role=acr,
            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'])
    _, obj_0 = self.generator.generate(all_models.Regulation, "regulation", {
        "regulation": {"title": "Test regulation", "context": None},
    })
    _, obj_1 = self.generator.generate(all_models.Regulation, "regulation", {
        "regulation": {"title": "Test regulation 2", "context": None},
    })
    response, rel = self.generator.generate(
        all_models.Relationship, "relationship", {
            "relationship": {"source": {
                "id": obj_0.id,
                "type": "Regulation"
            }, "destination": {
                "id": obj_1.id,
                "type": "Regulation"
            }, "context": None},
        }
    )
    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 section."""
      section_content = {"title": title, "context": None}
      if extra_data:
        section_content.update(**extra_data)
      return self.generator.generate(all_models.Section, "section", {
          "section": section_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 Section 1")

    self.api.set_user(self.users["creator"])
    acr_id = all_models.AccessControlRole.query.filter_by(
        object_type="Section",
        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 Section 2", linked_acl)
    obj2_acl = obj_2.access_control_list[0]
    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%2CClause%2CSection%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)
      verifier_role = all_models.AccessControlRole.query.filter_by(
          object_type="Assessment",
          name="Verifiers",
      ).first()
      factories.AccessControlListFactory(
          person=self.users["creator"],
          ac_role=verifier_role,
          object=asmnt,
      )

    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")
コード例 #26
0
ファイル: test_reader.py プロジェクト: Smotko/ggrc-core
class TestReader(TestCase):
  """ Test reader role """

  def setUp(self):
    super(TestReader, self).setUp()
    self.generator = Generator()
    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")]
    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):
    return
    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):
    return
    """ Test Basic create/read,update/delete operations """
    self.api.set_user(self.users["reader"])
    all_errors = []
    base_models = set([
        "Control", "Assessment", "DataAsset", "Contract",
        "Policy", "Regulation", "Standard", "Document", "Facility",
        "Market", "Objective", "OrgGroup", "Vendor", "Product",
        "Clause", "System", "Process", "Issue", "Project", "AccessGroup",
    ])
    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.api.post(model, {
            table_singular: {
                "title": model_singular,
                "context": None,
                "reference_url": "ref",
                "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 len(collection) == 0:
          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):
    return
    """ 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},
    })
    obj_id = response.json.get("policy").get("id")
    self.api.post(all_models.ObjectOwner, {"object_owner": {
        "person": {
            "id": self.users['reader'].id,
            "type": "Person",
        }, "ownable": {
            "type": "Policy",
            "id": obj_id,
        }, "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'])
    _, obj_0 = self.generator.generate(all_models.Regulation, "regulation", {
        "regulation": {"title": "Test regulation", "context": None},
    })
    _, obj_1 = self.generator.generate(all_models.Regulation, "regulation", {
        "regulation": {"title": "Test regulation 2", "context": None},
    })
    response, rel = self.generator.generate(
        all_models.Relationship, "relationship", {
            "relationship": {"source": {
                "id": obj_0.id,
                "type": "Regulation"
            }, "destination": {
                "id": obj_1.id,
                "type": "Regulation"
            }, "context": None},
        }
    )
    relationship_id = rel.id
    self.assertEqual(response.status_code, 201)
    self.api.set_user(self.users['reader'])
    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, 1)

  def test_creation_of_mappings(self):
    self.generator.api.set_user(self.users["admin"])
    _, control = self.generator.generate(all_models.Control, "control", {
        "control": {"title": "Test Control", "context": None},
    })
    self.generator.api.set_user(self.users['reader'])
    _, program = self.generator.generate(all_models.Program, "program", {
        "program": {"title": "Test Program", "context": None},
    })

    response, _ = self.generator.generate(
        all_models.Relationship, "relationship", {
            "relationship": {"destination": {
                "id": program.id,
                "type": "Program"
            }, "source": {
                "id": control.id,
                "type": "Control"
            }, "context": {
                "id": program.context.id,
                "type": "context"
            }},
        })
    self.assertEqual(response.status_code, 403)
コード例 #27
0
class TestAuditRBAC(TestCase):
  """Test audit RBAC"""
  # pylint: disable=too-many-instance-attributes

  CSV_DIR = join(abspath(dirname(__file__)), "test_csvs")

  def setUp(self):
    """Imports test_csvs/audit_rbac_snapshot_create.csv needed by the tests"""
    TestCase.clear_data()
    self.api = Api()
    self.objgen = integration.ggrc.generator.ObjectGenerator()

    self.csv_files = itertools.cycle([
        "audit_rbac_snapshot_create.csv",
        "audit_rbac_snapshot_update.csv"
    ])

    self._import_file(next(self.csv_files))
    self.people = all_models.Person.eager_query().all()

    self.program = db.session.query(all_models.Program).filter(
        all_models.Program.slug == "PMRBACPROGRAM-1"
    ).one()

    sources = set(r.source for r in self.program.related_sources)
    destinations = set(r.destination
                       for r in self.program.related_destinations)
    related = [obj for obj in sources.union(destinations)
               if not isinstance(obj, all_models.Person)]
    self.related_objects = related

    self.api = Api()
    self.client.get("/login")

    self.audit = self.create_audit()

    self.snapshots = all_models.Snapshot.eager_query().all()

    self.sanity_check()

  def create_audit(self):
    """Create default audit for audit snapshot RBAC tests"""
    _, audit = self.objgen.generate_object(all_models.Audit, {
        "title": "Snapshotable audit",
        "program": {"id": self.program.id},
        "status": "Planned",
        "snapshots": {
            "operation": "create",
        },
        "context": {
            "type": "Context",
            "id": self.program.context_id,
            "href": "/api/contexts/{}".format(self.program.context_id)
        }
    })
    self.add_auditors(audit)
    return audit

  def add_auditors(self, audit):
    """Add auditors to audits via POST user_role call"""
    auditor_emails = [
        "*****@*****.**",
        "*****@*****.**",
        "*****@*****.**",
        "*****@*****.**",
    ]
    program_reader_emails = [
        "*****@*****.**",
    ]
    auditor_role = db.session.query(all_models.Role).filter(
        all_models.Role.name == "Auditor"
    ).one()
    program_reader_role = db.session.query(all_models.Role).filter(
        all_models.Role.name == "ProgramReader"
    ).one()

    program = db.session.query(all_models.Program).filter(
        all_models.Program.slug == "PMRBACPROGRAM-1"
    ).one()

    user_roles = [
        (auditor_emails, auditor_role, audit.context),
        (program_reader_emails, program_reader_role, program.context)
    ]

    for emails, role, context in user_roles:
      for email in emails:
        auditor = all_models.Person.query.filter(
            all_models.Person.email == email).one()
        self.objgen.generate_user_role(auditor, role, context)

  def update_audit(self):
    """Update default audit"""
    self._import_file(next(self.csv_files))

    audit = all_models.Audit.query.filter(
        all_models.Audit.title == "Snapshotable audit"
    ).one()
    self.audit = audit

    self.api.modify_object(self.audit, {
        "snapshots": {
            "operation": "upsert"
        }
    })

  def sanity_check(self):
    """Sanity check if the audit_rbac.csv was imported correctly"""
    assert len(self.people) == 21, \
        "Expecting 21 people not {}.".format(len(self.people))
    assert len(self.related_objects) == 19, \
        "Expecting 19 objects mapped to program not {}.".format(
            len(self.related_objects))
    assert len(self.snapshots) == 19, \
        "Expecting 19 snapshots for default audit not {}.".format(
            len(self.snapshots))
    assert all(ss.parent_id == self.audit.id for ss in self.snapshots), \
        "All snapshots should be in default audit scope!"

  def read(self, objects):
    """Attempt to do a GET request for every object in the objects list"""
    responses = []
    for obj in objects:
      status_code = self.api.get(obj.__class__, obj.id).status_code
      responses.append((obj.type, status_code))
    return responses

  def update(self, objects):
    """Attempt to do a PUT request for every object in the objects list"""
    scope_response = self.api.get(self.audit.__class__, self.audit.id)
    if scope_response.status_code == 200:
      self.update_audit()

    responses = []
    for obj in objects:
      response = self.api.get(obj.__class__, obj.id)
      status_code = response.status_code
      if response.status_code == 200:
        data = response.json
        if obj.type == "Snapshot":
          data.update({
              "update_revision": "latest"
          })
        put_call = self.api.put(obj, data)
        status_code = put_call.status_code
      responses.append((obj.type, status_code))
    return responses

  def call_api(self, method, expected_statuses):
    """Calls the REST api with a given method and returns a list of
       status_codes that do not match the expected_statuses dict"""
    all_errors = []
    for person in self.people:
      self.api.set_user(person)
      responses = method(self.snapshots + [self.audit])
      for type_, code in responses:
        if code != expected_statuses[person.email][type_]:
          all_errors.append("{} does not have {} access to {} ({})".format(
              person.email, method.__name__, type_, code))
    return all_errors

  def test_read_access_on_mapped(self):
    """Test READ access to snapshotted objects of default audit"""
    expected_statuses = defaultdict(lambda: defaultdict(lambda: 200))
    exceptional_users = (
        ("*****@*****.**", DEFAULT_LACK_OF_PERMISSIONS),
    )
    for user, exceptions in exceptional_users:
      for type_, status_code in exceptions.items():
        expected_statuses[user][type_] = status_code
    errors = self.call_api(self.read, expected_statuses)
    assert not errors, "\n".join(errors)

  def test_update_access_on_mapped(self):
    """Test UPDATE access to snapshotted objects of default audit"""
    expected_statuses = defaultdict(lambda: defaultdict(lambda: 200))

    exceptional_users = (
        ("*****@*****.**", DEFAULT_LACK_OF_PERMISSIONS),
        ("*****@*****.**", DEFAULT_LACK_OF_PERMISSIONS),
        ("*****@*****.**", DEFAULT_LACK_OF_PERMISSIONS),
        ("*****@*****.**", DEFAULT_LACK_OF_PERMISSIONS),
        # Auditor roles
        ("*****@*****.**", DEFAULT_AUDITOR_PERMISSIONS),
        ("*****@*****.**", DEFAULT_AUDITOR_PERMISSIONS)
    )

    for user, exceptions in exceptional_users:
      for type_, status_code in exceptions.items():
        expected_statuses[user][type_] = status_code

    errors = self.call_api(self.update, expected_statuses)
    assert not errors, "\n".join(errors)
コード例 #28
0
class TestPermissions(TestCase):
    """Test checks permissions for proposals."""
    def setUp(self):
        super(TestPermissions, self).setUp()
        self.api = Api()
        roles = {r.name: r for r in all_models.Role.query.all()}
        ac_roles = {
            r.name: r
            for r in all_models.AccessControlRole.query.all()
        }
        with factories.single_commit():
            self.control = factories.ControlFactory()
            acrs = {
                "ACL_Reader":
                factories.AccessControlRoleFactory(name="ACL_Reader",
                                                   object_type="Control",
                                                   update=0),
                "ACL_Editor":
                factories.AccessControlRoleFactory(name="ACL_Editor",
                                                   object_type="Control"),
                "ACL_Nobody":
                factories.AccessControlRoleFactory(
                    name="ACL_Nobody",
                    object_type="Control",
                    read=0,
                    update=0,
                    delete=0,
                ),
            }
            self.program = factories.ProgramFactory()
            self.program.context.related_object = self.program
            self.relationship = factories.RelationshipFactory(
                source=self.program,
                destination=self.control,
                context=self.program.context,
            )
            self.people = {
                "Creator": factories.PersonFactory(),
                "Reader": factories.PersonFactory(),
                "Editor": factories.PersonFactory(),
                "Administrator": factories.PersonFactory(),
                "ACL_Reader": factories.PersonFactory(),
                "ACL_Editor": factories.PersonFactory(),
                "ACL_Nobody": factories.PersonFactory(),
                "Program Editors": factories.PersonFactory(),
                "Program Managers": factories.PersonFactory(),
                "Program Readers": factories.PersonFactory(),
            }
            for role_name in ["Creator", "Reader", "Editor", "Administrator"]:
                rbac_factories.UserRoleFactory(role=roles[role_name],
                                               person=self.people[role_name])
            for role_name in [
                    "Program Editors", "Program Managers", "Program Readers"
            ]:
                person = self.people[role_name]
                rbac_factories.UserRoleFactory(role=roles["Creator"],
                                               person=person)
                factories.AccessControlListFactory(
                    ac_role=ac_roles[role_name],
                    object=self.program,
                    person=person,
                )
            self.proposal = factories.ProposalFactory(
                instance=self.control,
                content={
                    "access_control_list": {},
                    "custom_attribute_values": {},
                    "fields": {},
                    "mapping_fields": {},
                    "mapping_list_fields": {},
                })
            factories.RelationshipFactory(
                source=self.control,
                destination=self.proposal,
            )

            for role_name in ["ACL_Reader", "ACL_Editor", "ACL_Nobody"]:
                person = self.people[role_name]
                rbac_factories.UserRoleFactory(role=roles["Creator"],
                                               person=person)
                factories.AccessControlListFactory(
                    ac_role=acrs[role_name],
                    object=self.control,
                    person=person,
                )

    @ddt.data(
        ("Creator", 403),
        ("Reader", 200),
        ("Editor", 200),
        ("ACL_Reader", 200),
        ("ACL_Editor", 200),
        ("ACL_Nobody", 403),
        ("Administrator", 200),
        ("Program Editors", 200),
        ("Program Managers", 200),
        ("Program Readers", 200),
    )
    @ddt.unpack
    def test_permissions_on_get(self, role_name, status):
        """Test get proposals for {0}."""
        proposal_id = self.proposal.id
        self.api.set_user(self.people[role_name])
        self.client.get("/login")
        resp = self.api.get(all_models.Proposal, proposal_id)
        self.assertEqual(status, resp.status_code)

    def api_proposal_status_change(self, proposal_id, status):
        return self.api.put(all_models.Proposal.query.get(proposal_id),
                            {"proposal": {
                                "status": status
                            }})

    @ddt.data(("Creator", 403), ("Reader", 403), ("Editor", 200),
              ("Administrator", 200), ("ACL_Reader", 403), ("ACL_Editor", 200),
              ("ACL_Nobody", 403), ("Program Editors", 200),
              ("Program Managers", 200), ("Program Readers", 403))
    @ddt.unpack
    def test_permissions_on_apply(self, role_name, status):
        """Test apply proposals for {0}."""
        proposal_id = self.proposal.id
        self.api.set_user(self.people[role_name])
        self.client.get("/login")
        resp = self.api_proposal_status_change(
            proposal_id, all_models.Proposal.STATES.APPLIED)
        self.assertEqual(status, resp.status_code)

    @ddt.data(
        ("Creator", 403),
        ("Reader", 403),
        ("Editor", 200),
        ("ACL_Reader", 403),
        ("ACL_Editor", 200),
        ("ACL_Nobody", 403),
        ("Administrator", 200),
        ("Program Editors", 200),
        ("Program Managers", 200),
        ("Program Readers", 403),
    )
    @ddt.unpack
    def test_permissions_on_decline(self, role_name, status):
        """Test decline proposals for {0}."""
        proposal_id = self.proposal.id
        self.api.set_user(self.people[role_name])
        self.client.get("/login")
        resp = self.api_proposal_status_change(
            proposal_id, all_models.Proposal.STATES.DECLINED)
        self.assertEqual(status, resp.status_code)

    @ddt.data(
        ("Creator", 403),
        ("Reader", 201),
        ("Editor", 201),
        ("ACL_Reader", 201),
        ("ACL_Editor", 201),
        ("ACL_Nobody", 403),
        ("Administrator", 201),
        ("Program Editors", 201),
        ("Program Managers", 201),
        ("Program Readers", 201),
    )
    @ddt.unpack
    def test_permissions_on_create(self, role_name, status):
        """Test create proposal for {0}."""
        data = {
            "proposal": {
                "instance": {
                    "id": self.control.id,
                    "type": self.control.type,
                },
                "full_instance_content": {
                    "title": "new_title"
                },
                "agenda": "update cav",
                "context": None,
            }
        }
        self.api.set_user(self.people[role_name])
        self.client.get("/login")
        resp = self.api.post(all_models.Proposal, data)
        self.assertEqual(status, resp.status_code)

    @ddt.data(
        ("Creator", 0),
        ("Reader", 1),
        ("Editor", 1),
        # Following two tests have been commented out as the functionality for
        # custom role propagation has been temporarily removed This test should
        # be enabled back in scope of ticket GGRC-4991
        # ("ACL_Reader", 1),
        # ("ACL_Editor", 1),
        ("ACL_Nobody", 0),
        ("Administrator", 1),
        ("Program Editors", 1),
        ("Program Managers", 1),
        ("Program Readers", 1),
    )
    @ddt.unpack
    def test_query_filter(self, role_name, expected_count):
        """Test query proposals for {0}.

    Args:
        role_name: string, unique key,
                   shows the position of user in generated infrustructure
        expected_count: int, number of proposals,
                        that should be filtered by query
    """
        control_id = self.control.id
        data = [{
            "limit": [0, 5],
            "object_name":
            all_models.Proposal.__name__,
            "order_by": [
                {
                    "name": "status",
                    "desc": True
                },
                {
                    "name": "created_at",
                    "desc": True
                },
            ],
            "filters": {
                "expression": {
                    "left": {
                        "left": "instance_type",
                        "op": {
                            "name": "="
                        },
                        "right": self.control.type,
                    },
                    "op": {
                        "name": "AND"
                    },
                    "right": {
                        "left": "instance_id",
                        "op": {
                            "name": "="
                        },
                        "right": control_id,
                    },
                },
            },
        }]
        self.api.set_user(self.people[role_name])
        self.client.get("/login")
        headers = {
            "Content-Type": "application/json",
        }
        resp = self.api.client.post("/query",
                                    data=json.dumps(data),
                                    headers=headers).json
        self.assertEqual(1, len(resp))
        self.assertEqual(expected_count, resp[0]["Proposal"]["count"])